/* This file is part of leafdigital leafChat. leafChat is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. leafChat is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with leafChat. If not, see <http://www.gnu.org/licenses/>. Copyright 2011 Samuel Marshall. */ package com.leafdigital.donations; import java.io.IOException; import java.net.*; import util.PlatformUtils; import com.leafdigital.prefs.api.*; import com.leafdigital.ui.api.*; import leafchat.core.api.*; /** * Plugin that handles donation reminders. */ @UIHandler({"beg", "didyou"}) public class DonationsPlugin implements Plugin { private final static String PREF_NOTDONATEDVERSION="notdonated-version", PREF_NOTDONATEDTIME="notdonated-time", PREF_NOTDONATEDUSES="notdonated-uses", PREF_DONATEDVERSION="donated-version", PREF_DONATEDTIME="donated-time", PREF_HIDEPROMPTUNTIL="hide-prompt-until", PREF_CHECKDONATION="check-donation"; private final static String DONATEURL="http://www.leafdigital.com/software/leafchat/donate.html"; private final static long YEAR=365L*24L*60L*60L*1000L; private final static long THREEMONTHS=91L*24L*60L*60L*1000L; private final static long TWOMONTHS=60L*24L*60L*60L*1000L; private PluginContext context; private Dialog d; /** Donation message. */ public Label messageUI; @Override public void init(PluginContext context, PluginLoadReporter reporter) throws GeneralException { this.context=context; context.requestMessages(SystemStateMsg.class,this,Msg.PRIORITY_EARLY); } /** * Message: System state. Used to display dialog if needed. * @param msg Message * @throws GeneralException */ public void msg(SystemStateMsg msg) throws GeneralException { if(msg.getType()!=SystemStateMsg.UIREADY) return; UI ui=context.getSingle(UI.class); Preferences prefs=context.getSingle(Preferences.class); PreferencesGroup group=prefs.getGroup(this); // Do we need to check a donation? if(group.get(PREF_CHECKDONATION,"").equals("y")) { group.unset(PREF_CHECKDONATION); d = ui.createDialog("didyou", this); d.show(null); return; } // Have we donated for the current version? If so do nothing if(group.get(PREF_DONATEDVERSION,"").equals(SystemVersion.getBuildVersion())) return; // OK, did we already store the not-donated version id? if(group.get(PREF_NOTDONATEDVERSION,null)==null) { // Nope. Store it now group.set(PREF_NOTDONATEDVERSION,SystemVersion.getBuildVersion()); group.set(PREF_NOTDONATEDTIME,System.currentTimeMillis()+""); group.set(PREF_NOTDONATEDUSES,"1"); return; } // Count uses of undonated version int undonatedUses=prefs.toInt(group.get(PREF_NOTDONATEDUSES)); group.set(PREF_NOTDONATEDUSES,prefs.fromInt(undonatedUses+1)); // If they have donated, we don't ask for a year at least String donatedTime=group.get(PREF_DONATEDTIME,null); if(donatedTime!=null && System.currentTimeMillis() < Long.parseLong(donatedTime) + YEAR) return; // We also don't ask until three months and 30 usages since the undonated // version (or first run) long undonatedTime=Long.parseLong(group.get(PREF_NOTDONATEDTIME)); if(System.currentTimeMillis() < undonatedTime+ THREEMONTHS) return; if(undonatedUses<30) return; // If they told us to piss off, let's take note long hidePromptUntil=Long.parseLong(group.get(PREF_HIDEPROMPTUNTIL,"0")); if(System.currentTimeMillis()<hidePromptUntil) return; group.unset(PREF_HIDEPROMPTUNTIL); // Okay, now show the dialog long undonatedDays=(System.currentTimeMillis()-undonatedTime)/(24*60*60*1000); d = ui.createDialog("beg", this); if(donatedTime==null) { messageUI.setText( "<para>leafChat is free for noncommercial use, but if you like it, "+ "please consider making a donation.</para>"+ "<para>A lot of work went into this program and it would be nice to "+ "pay for it (think of it like busking). You've "+ "used leafChat <key>"+undonatedUses+"</key> times over <key>"+ undonatedDays+"</key> days, so I hope you like it.</para>"+ "<para>You can donate via PayPal or using any credit card. Click the "+ "<strong>Donate</strong> button to open the relevant Web page.</para>"+ "<para>If you don't want to donate now, no problem. Just click "+ "<strong>Maybe later</strong> and this box will go away for a couple "+ "of months.</para>"+ "<small>If you already made a donation without going through the "+ "program interface, click Donate anyway; you can just close the page "+ "again.</small>" ); } else { messageUI.setText( "<para>Thanks for previously donating to show your appreciation for " + "leafChat.</para>"+ "<para>That was over a year ago. Since then you've updated to at least one new version and "+ "have used that new version <key>"+undonatedUses+"</key> times over <key>"+ undonatedDays+"</key> days.</para>"+ "<para>If you think you've got enough value out of the updates that "+ "another donation would be fair, then please click <strong>Donate</strong> "+ "now. Otherwise? No worries, just click <strong>Maybe later</strong>.</para>"+ "<small>If you made a donation recently without going through the "+ "program interface, click Donate anyway; you can just close the page "+ "again.</small>" ); } d.show(null); } @Override public void close() throws GeneralException { // Perform any cleanup necessary when your plugin is closed, such as closing // files. (Requests made on the context object are automatically cleaned // up, so you may be able to leave this blank.) } @Override public String toString() { // Used to display in system log etc. return "Donation prompts plugin"; } /** Action: Donate button. */ @UIAction public void actionDonate() { d.close(); Preferences prefs=context.getSingle(Preferences.class); PreferencesGroup group=prefs.getGroup(this); group.set(PREF_CHECKDONATION,"y"); try { PlatformUtils.showBrowser(new URL(DONATEURL)); } catch(MalformedURLException e) { // Can't happen } catch(IOException e) { UI ui=context.getSingle(UI.class); ui.showUserError(null,"Unable to open browser", "leafChat was unable to open your Web browser. Please visit the " + "donation page manually; it is "+DONATEURL); } } /** Action: Yes, I donated. */ @UIAction public void actionYep() { d.close(); Preferences prefs=context.getSingle(Preferences.class); PreferencesGroup group=prefs.getGroup(this); group.set(PREF_DONATEDTIME,System.currentTimeMillis()+""); group.set(PREF_DONATEDVERSION,SystemVersion.getBuildVersion()); group.unset(PREF_NOTDONATEDTIME); group.unset(PREF_NOTDONATEDUSES); group.unset(PREF_NOTDONATEDVERSION); } /** Action: Cancel dialog. */ @UIAction public void actionCancel() { d.close(); } /** Action: Maybe later (button). */ @UIAction public void actionLater() { d.close(); Preferences prefs=context.getSingle(Preferences.class); PreferencesGroup group=prefs.getGroup(this); group.set(PREF_HIDEPROMPTUNTIL,(System.currentTimeMillis()+TWOMONTHS)+""); } }