summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gui/backend.go11
-rw-r--r--gui/handlers.cpp16
-rw-r--r--gui/handlers.h4
-rw-r--r--gui/qml/DonateDialog.qml5
-rw-r--r--gui/qml/main.qml7
-rw-r--r--pkg/backend/api.go29
-rw-r--r--pkg/backend/bitmask.go19
-rw-r--r--pkg/backend/donate.go35
-rw-r--r--pkg/backend/status.go103
-rw-r--r--pkg/config/gui.go14
10 files changed, 158 insertions, 85 deletions
diff --git a/gui/backend.go b/gui/backend.go
index 9c65025..ab96edb 100644
--- a/gui/backend.go
+++ b/gui/backend.go
@@ -31,9 +31,14 @@ func Quit() {
}
-//export ToggleDonate
-func ToggleDonate() {
- backend.ToggleDonate()
+//export DonateAccepted
+func DonateAccepted() {
+ backend.DonateAccepted()
+}
+
+//export DonateRejected
+func DonateRejected() {
+ backend.DonateRejected()
}
//export SubscribeToEvent
diff --git a/gui/handlers.cpp b/gui/handlers.cpp
index e37de2d..39a5746 100644
--- a/gui/handlers.cpp
+++ b/gui/handlers.cpp
@@ -1,5 +1,7 @@
#include <QTimer>
#include <QDebug>
+#include <QDesktopServices>
+#include <QUrl>
#include "handlers.h"
#include "lib/libgoshim.h"
@@ -23,9 +25,19 @@ void Backend::unblock()
Unblock();
}
-void Backend::toggleDonate()
+void Backend::donateAccepted()
{
- ToggleDonate();
+ DonateAccepted();
+}
+
+void Backend::donateRejected()
+{
+ DonateRejected();
+}
+
+void Backend::openURL(QString link)
+{
+ QDesktopServices::openUrl(QUrl(link));
}
void Backend::quit()
diff --git a/gui/handlers.h b/gui/handlers.h
index 3fe9eed..e65fd5e 100644
--- a/gui/handlers.h
+++ b/gui/handlers.h
@@ -33,7 +33,9 @@ public slots:
void switchOn();
void switchOff();
void unblock();
- void toggleDonate();
+ void donateAccepted();
+ void donateRejected();
+ void openURL(QString link);
void quit();
};
diff --git a/gui/qml/DonateDialog.qml b/gui/qml/DonateDialog.qml
index b7431ab..eb761a4 100644
--- a/gui/qml/DonateDialog.qml
+++ b/gui/qml/DonateDialog.qml
@@ -16,12 +16,13 @@ MessageDialog {
onAccepted: {
if (backend) {
- backend.donateAccepted(true)
+ backend.openURL(ctx.donateURL)
+ backend.donateAccepted()
}
}
onRejected: {
if (backend) {
- backend.donateAccepted(false)
+ backend.donateRejected()
}
}
}
diff --git a/gui/qml/main.qml b/gui/qml/main.qml
index 98eac80..65c09cb 100644
--- a/gui/qml/main.qml
+++ b/gui/qml/main.qml
@@ -16,10 +16,9 @@ ApplicationWindow {
target: jsonModel
onDataChanged: {
ctx = JSON.parse(jsonModel.getJson());
- if (ctx.donate == 'true') {
+ if (ctx.donateDialog == 'true') {
console.debug(jsonModel.getJson())
donate.visible = true
- backend.toggleDonate()
}
}
}
@@ -171,7 +170,9 @@ ApplicationWindow {
MenuItem {
text: qsTr("Donate...")
visible: true
- //onTriggered: donate.open()
+ onTriggered: {
+ donate.visible = true
+ }
}
MenuItem {
diff --git a/pkg/backend/api.go b/pkg/backend/api.go
index f924cbd..5cb0304 100644
--- a/pkg/backend/api.go
+++ b/pkg/backend/api.go
@@ -6,6 +6,7 @@ import (
"C"
"fmt"
"log"
+ "time"
"unsafe"
"0xacab.org/leap/bitmask-vpn/pkg/bitmask"
@@ -23,18 +24,24 @@ func SwitchOff() {
}
func Unblock() {
+ //TODO
fmt.Println("unblock... [not implemented]")
}
func Quit() {
if ctx.Status != off {
go setStatus(stopping)
+ ctx.cfg.SetUserStoppedVPN(true)
stopVPN()
}
}
-func ToggleDonate() {
- toggleDonate()
+func DonateAccepted() {
+ donateAccepted()
+}
+
+func DonateRejected() {
+ donateRejected()
}
func SubscribeToEvent(event string, f unsafe.Pointer) {
@@ -42,21 +49,23 @@ func SubscribeToEvent(event string, f unsafe.Pointer) {
}
func InitializeBitmaskContext() {
- pi := bitmask.GetConfiguredProvider()
+ p := bitmask.GetConfiguredProvider()
initOnce.Do(func() {
- initializeContext(pi.Provider, pi.AppName)
+ initializeContext(
+ p.Provider, p.AppName)
})
go ctx.updateStatus()
- /* DEBUG
- timer := time.NewTimer(time.Second * 3)
go func() {
- <-timer.C
- fmt.Println("donate timer fired")
- toggleDonate()
+ if needsDonationReminder() {
+ // wait a bit before launching reminder
+ timer := time.NewTimer(time.Minute * 5)
+ <-timer.C
+ showDonate()
+ }
+
}()
- */
}
func RefreshContext() *C.char {
diff --git a/pkg/backend/bitmask.go b/pkg/backend/bitmask.go
index 07d27ea..8fd2367 100644
--- a/pkg/backend/bitmask.go
+++ b/pkg/backend/bitmask.go
@@ -5,6 +5,7 @@ import (
"os"
"0xacab.org/leap/bitmask-vpn/pkg/bitmask"
+ "0xacab.org/leap/bitmask-vpn/pkg/config"
)
func initializeBitmask() {
@@ -19,6 +20,7 @@ func initializeBitmask() {
log.Println("error: cannot initialize bitmask")
}
ctx.bm = b
+ ctx.cfg = config.ParseConfig()
}
func startVPN() {
@@ -36,16 +38,25 @@ func stopVPN() {
}
}
+func wantDonations() bool {
+ if config.AskForDonations == "true" {
+ return true
+ }
+ return false
+}
+
// initializeContext initializes an empty connStatus and assigns it to the
// global ctx holder. This is expected to be called only once, so the public
// api uses the sync.Once primitive to call this.
func initializeContext(provider, appName string) {
var st status = off
ctx = &connectionCtx{
- AppName: appName,
- Provider: provider,
- Donate: false,
- Status: st,
+ AppName: appName,
+ Provider: provider,
+ DonateURL: config.DonateURL,
+ AskForDonations: wantDonations(),
+ DonateDialog: false,
+ Status: st,
}
go trigger(OnStatusChanged)
initializeBitmask()
diff --git a/pkg/backend/donate.go b/pkg/backend/donate.go
new file mode 100644
index 0000000..d216687
--- /dev/null
+++ b/pkg/backend/donate.go
@@ -0,0 +1,35 @@
+package backend
+
+import (
+ "log"
+ "time"
+)
+
+func needsDonationReminder() bool {
+ return ctx.cfg.NeedsDonationReminder()
+}
+
+func donateAccepted() {
+ stmut.Lock()
+ defer stmut.Unlock()
+ ctx.DonateDialog = false
+ log.Println("marking as donated")
+ ctx.cfg.SetDonated()
+ go trigger(OnStatusChanged)
+}
+
+func donateRejected() {
+ timer := time.NewTimer(time.Hour)
+ go func() {
+ <-timer.C
+ showDonate()
+ }()
+}
+
+func showDonate() {
+ stmut.Lock()
+ defer stmut.Unlock()
+ ctx.DonateDialog = true
+ ctx.cfg.SetLastReminded()
+ go trigger(OnStatusChanged)
+}
diff --git a/pkg/backend/status.go b/pkg/backend/status.go
index e2d31db..7e9f211 100644
--- a/pkg/backend/status.go
+++ b/pkg/backend/status.go
@@ -6,6 +6,7 @@ import (
"log"
"0xacab.org/leap/bitmask-vpn/pkg/bitmask"
+ "0xacab.org/leap/bitmask-vpn/pkg/config"
)
const (
@@ -20,60 +21,20 @@ const (
// if we ever switch again to a provider-agnostic app, we should keep a map here.
var ctx *connectionCtx
-// the status type reflects the current VPN status. Go code is responsible for updating
-// it; the C gui just watches its changes and pulls its updates via the serialized
-// context object.
-
-type status int
-
-const (
- off status = iota
- starting
- on
- stopping
- failed
- unknown
-)
-
-func (s status) String() string {
- return [...]string{offStr, startingStr, onStr, stoppingStr, failedStr}[s]
-}
-
-func (s status) MarshalJSON() ([]byte, error) {
- b := bytes.NewBufferString(`"`)
- b.WriteString(s.String())
- b.WriteString(`"`)
- return b.Bytes(), nil
-}
-
-func (s status) fromString(st string) status {
- switch st {
- case offStr:
- return off
- case startingStr:
- return starting
- case onStr:
- return on
- case stoppingStr:
- return stopping
- case failedStr:
- return failed
- default:
- return unknown
- }
-}
-
// The connectionCtx keeps the global state that is passed around to C-land. It
// also serves as the primary way of passing requests from the frontend to the
// Go-core, by letting the UI write some of these variables and processing
// them.
type connectionCtx struct {
- AppName string `json:"appName"`
- Provider string `json:"provider"`
- Donate bool `json:"donate"`
- Status status `json:"status"`
- bm bitmask.Bitmask
+ AppName string `json:"appName"`
+ Provider string `json:"provider"`
+ AskForDonations bool `json:"askForDonations"`
+ DonateDialog bool `json:"donateDialog"`
+ DonateURL string `json:"donateURL"`
+ Status status `json:"status"`
+ bm bitmask.Bitmask
+ cfg *config.Config
}
func (c connectionCtx) toJson() ([]byte, error) {
@@ -110,11 +71,47 @@ func setStatus(st status) {
go trigger(OnStatusChanged)
}
-func toggleDonate() {
- stmut.Lock()
- defer stmut.Unlock()
- ctx.Donate = !ctx.Donate
- go trigger(OnStatusChanged)
+// the status type reflects the current VPN status. Go code is responsible for updating
+// it; the C gui just watches its changes and pulls its updates via the serialized
+// context object.
+
+type status int
+
+const (
+ off status = iota
+ starting
+ on
+ stopping
+ failed
+ unknown
+)
+
+func (s status) String() string {
+ return [...]string{offStr, startingStr, onStr, stoppingStr, failedStr}[s]
+}
+
+func (s status) MarshalJSON() ([]byte, error) {
+ b := bytes.NewBufferString(`"`)
+ b.WriteString(s.String())
+ b.WriteString(`"`)
+ return b.Bytes(), nil
+}
+
+func (s status) fromString(st string) status {
+ switch st {
+ case offStr:
+ return off
+ case startingStr:
+ return starting
+ case onStr:
+ return on
+ case stoppingStr:
+ return stopping
+ case failedStr:
+ return failed
+ default:
+ return unknown
+ }
}
func setStatusFromStr(stStr string) {
diff --git a/pkg/config/gui.go b/pkg/config/gui.go
index ce3f14d..5fa4886 100644
--- a/pkg/config/gui.go
+++ b/pkg/config/gui.go
@@ -37,7 +37,7 @@ var (
// Config holds the configuration of the systray
type Config struct {
file struct {
- LastNotification time.Time
+ LastReminded time.Time
Donated time.Time
SelectGateway bool
Obfs4 bool
@@ -77,16 +77,16 @@ func (c *Config) SetUserStoppedVPN(vpnStopped bool) error {
return c.save()
}
-func (c *Config) HasDonated() bool {
- return c.file.Donated.Add(oneMonth).After(time.Now())
+func (c *Config) NeedsDonationReminder() bool {
+ return !c.hasDonated() && c.file.LastReminded.Add(oneDay).Before(time.Now())
}
-func (c *Config) NeedsNotification() bool {
- return !c.HasDonated() && c.file.LastNotification.Add(oneDay).Before(time.Now())
+func (c *Config) hasDonated() bool {
+ return c.file.Donated.Add(oneMonth).After(time.Now())
}
-func (c *Config) SetNotification() error {
- c.file.LastNotification = time.Now()
+func (c *Config) SetLastReminded() error {
+ c.file.LastReminded = time.Now()
return c.save()
}