From 168f8d37a363f6e1e128f43e180b070812729f32 Mon Sep 17 00:00:00 2001 From: atavism Date: Sun, 26 Nov 2023 03:07:10 -0800 Subject: [PATCH] show bottom bar, updates to show translations and plans + checkout pages --- desktop/lib.go | 15 + desktop/pro/pro.pb.go | 195 ++--- desktop/pro/pro.proto | 18 +- lib/app_desktop.dart | 54 -- lib/core/router/router.dart | 11 +- lib/core/router/router.gr.dart | 800 ++++++++++--------- lib/desktop/account.dart | 111 +++ lib/desktop/account_tab.dart | 9 + lib/desktop/app.dart | 117 +++ lib/desktop/custom_bottom_bar.dart | 223 ++++++ lib/desktop/custom_bottom_item.dart | 147 ++++ lib/{ => desktop}/ffi.dart | 12 + lib/desktop/home.dart | 55 ++ lib/{main_desktop.dart => desktop/main.dart} | 5 +- lib/desktop/plans.dart | 216 +++++ lib/home.dart | 18 +- lib/i18n/i18n.dart | 2 + lib/plans/plans.dart | 326 ++++---- lib/plans/utils.dart | 8 + lib/vpn/vpn_pro_banner.dart | 2 +- lib/vpn/vpn_switch.dart | 2 +- 21 files changed, 1641 insertions(+), 705 deletions(-) delete mode 100644 lib/app_desktop.dart create mode 100644 lib/desktop/account.dart create mode 100644 lib/desktop/account_tab.dart create mode 100644 lib/desktop/app.dart create mode 100644 lib/desktop/custom_bottom_bar.dart create mode 100644 lib/desktop/custom_bottom_item.dart rename lib/{ => desktop}/ffi.dart (68%) create mode 100644 lib/desktop/home.dart rename lib/{main_desktop.dart => desktop/main.dart} (79%) create mode 100644 lib/desktop/plans.dart diff --git a/desktop/lib.go b/desktop/lib.go index 3a7ca64b7..3124ea518 100644 --- a/desktop/lib.go +++ b/desktop/lib.go @@ -10,6 +10,7 @@ import ( "runtime" "runtime/debug" "strconv" + "sync" "github.com/getlantern/appdir" "github.com/getlantern/android-lantern/desktop/app" @@ -23,6 +24,8 @@ import "C" var ( log = golog.LoggerFor("lantern-desktop.main") + selectedTab = "account" + selectedTabMu sync.Mutex proClient *pro.ProClient settings *app.Settings ) @@ -84,6 +87,18 @@ func sendError(err error) *C.char { return C.CString(string(b)) } +//export SelectedTab +func SelectedTab() *C.char { + return C.CString(selectedTab) +} + +//export SetSelectTab +func SetSelectTab(tab string) { + selectedTabMu.Lock() + defer selectedTabMu.Unlock() + selectedTab = tab +} + //export Plans func Plans() *C.char { deviceID, userID, token := userHeaders() diff --git a/desktop/pro/pro.pb.go b/desktop/pro/pro.pb.go index 42bdeac77..034571a80 100644 --- a/desktop/pro/pro.pb.go +++ b/desktop/pro/pro.pb.go @@ -203,14 +203,16 @@ type Plan struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` - Duration *Duration `protobuf:"bytes,3,opt,name=duration,proto3" json:"duration,omitempty"` - Price map[string]uint32 `protobuf:"bytes,4,rep,name=price,proto3" json:"price,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"` - ExpectedMonthlyPrice map[string]uint32 `protobuf:"bytes,5,rep,name=expectedMonthlyPrice,proto3" json:"expectedMonthlyPrice,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"` - UsdPrice uint32 `protobuf:"varint,6,opt,name=usdPrice,proto3" json:"usdPrice,omitempty"` - UsdPrice1Y uint32 `protobuf:"varint,7,opt,name=usdPrice1Y,proto3" json:"usdPrice1Y,omitempty"` - UsdPrice2Y uint32 `protobuf:"varint,8,opt,name=usdPrice2Y,proto3" json:"usdPrice2Y,omitempty"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` + BestValue bool `protobuf:"varint,3,opt,name=bestValue,proto3" json:"bestValue,omitempty"` + UsdPrice int64 `protobuf:"varint,4,opt,name=usdPrice,proto3" json:"usdPrice,omitempty"` + Price map[string]int64 `protobuf:"bytes,5,rep,name=price,proto3" json:"price,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"` + TotalCostBilledOneTime string `protobuf:"bytes,6,opt,name=totalCostBilledOneTime,proto3" json:"totalCostBilledOneTime,omitempty"` + OneMonthCost string `protobuf:"bytes,7,opt,name=oneMonthCost,proto3" json:"oneMonthCost,omitempty"` + TotalCost string `protobuf:"bytes,8,opt,name=totalCost,proto3" json:"totalCost,omitempty"` + FormattedBonus string `protobuf:"bytes,9,opt,name=formattedBonus,proto3" json:"formattedBonus,omitempty"` + RenewalText string `protobuf:"bytes,10,opt,name=renewalText,proto3" json:"renewalText,omitempty"` } func (x *Plan) Reset() { @@ -259,46 +261,60 @@ func (x *Plan) GetDescription() string { return "" } -func (x *Plan) GetDuration() *Duration { +func (x *Plan) GetBestValue() bool { if x != nil { - return x.Duration + return x.BestValue } - return nil + return false } -func (x *Plan) GetPrice() map[string]uint32 { +func (x *Plan) GetUsdPrice() int64 { + if x != nil { + return x.UsdPrice + } + return 0 +} + +func (x *Plan) GetPrice() map[string]int64 { if x != nil { return x.Price } return nil } -func (x *Plan) GetExpectedMonthlyPrice() map[string]uint32 { +func (x *Plan) GetTotalCostBilledOneTime() string { if x != nil { - return x.ExpectedMonthlyPrice + return x.TotalCostBilledOneTime } - return nil + return "" } -func (x *Plan) GetUsdPrice() uint32 { +func (x *Plan) GetOneMonthCost() string { if x != nil { - return x.UsdPrice + return x.OneMonthCost } - return 0 + return "" } -func (x *Plan) GetUsdPrice1Y() uint32 { +func (x *Plan) GetTotalCost() string { if x != nil { - return x.UsdPrice1Y + return x.TotalCost } - return 0 + return "" } -func (x *Plan) GetUsdPrice2Y() uint32 { +func (x *Plan) GetFormattedBonus() string { if x != nil { - return x.UsdPrice2Y + return x.FormattedBonus } - return 0 + return "" +} + +func (x *Plan) GetRenewalText() string { + if x != nil { + return x.RenewalText + } + return "" } type PlansResponse struct { @@ -542,64 +558,62 @@ var file_desktop_pro_pro_proto_rawDesc = []byte{ 0x73, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x73, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6d, 0x73, 0x67, 0x22, 0x26, 0x0a, 0x08, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0d, 0x52, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xbb, 0x03, 0x0a, 0x04, + 0x0d, 0x52, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x98, 0x03, 0x0a, 0x04, 0x50, 0x6c, 0x61, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x0a, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x26, 0x0a, - 0x05, 0x70, 0x72, 0x69, 0x63, 0x65, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x50, - 0x6c, 0x61, 0x6e, 0x2e, 0x50, 0x72, 0x69, 0x63, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x05, - 0x70, 0x72, 0x69, 0x63, 0x65, 0x12, 0x53, 0x0a, 0x14, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, - 0x64, 0x4d, 0x6f, 0x6e, 0x74, 0x68, 0x6c, 0x79, 0x50, 0x72, 0x69, 0x63, 0x65, 0x18, 0x05, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x50, 0x6c, 0x61, 0x6e, 0x2e, 0x45, 0x78, 0x70, 0x65, 0x63, - 0x74, 0x65, 0x64, 0x4d, 0x6f, 0x6e, 0x74, 0x68, 0x6c, 0x79, 0x50, 0x72, 0x69, 0x63, 0x65, 0x45, - 0x6e, 0x74, 0x72, 0x79, 0x52, 0x14, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x4d, 0x6f, - 0x6e, 0x74, 0x68, 0x6c, 0x79, 0x50, 0x72, 0x69, 0x63, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, - 0x64, 0x50, 0x72, 0x69, 0x63, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x75, 0x73, - 0x64, 0x50, 0x72, 0x69, 0x63, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x75, 0x73, 0x64, 0x50, 0x72, 0x69, - 0x63, 0x65, 0x31, 0x59, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x75, 0x73, 0x64, 0x50, - 0x72, 0x69, 0x63, 0x65, 0x31, 0x59, 0x12, 0x1e, 0x0a, 0x0a, 0x75, 0x73, 0x64, 0x50, 0x72, 0x69, - 0x63, 0x65, 0x32, 0x59, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x75, 0x73, 0x64, 0x50, - 0x72, 0x69, 0x63, 0x65, 0x32, 0x59, 0x1a, 0x38, 0x0a, 0x0a, 0x50, 0x72, 0x69, 0x63, 0x65, 0x45, - 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, - 0x1a, 0x47, 0x0a, 0x19, 0x45, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x4d, 0x6f, 0x6e, 0x74, - 0x68, 0x6c, 0x79, 0x50, 0x72, 0x69, 0x63, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, - 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, - 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x2c, 0x0a, 0x0d, 0x50, 0x6c, 0x61, - 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1b, 0x0a, 0x05, 0x70, 0x6c, - 0x61, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x05, 0x2e, 0x50, 0x6c, 0x61, 0x6e, - 0x52, 0x05, 0x70, 0x6c, 0x61, 0x6e, 0x73, 0x22, 0x46, 0x0a, 0x06, 0x44, 0x65, 0x76, 0x69, 0x63, - 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, - 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x22, - 0x9e, 0x02, 0x0a, 0x13, 0x55, 0x73, 0x65, 0x72, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, - 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, - 0x6f, 0x64, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x66, - 0x65, 0x72, 0x72, 0x61, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x66, - 0x65, 0x72, 0x72, 0x61, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x1e, 0x0a, 0x0a, 0x75, - 0x73, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0a, 0x75, 0x73, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x6c, - 0x6f, 0x63, 0x61, 0x6c, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6c, 0x6f, 0x63, - 0x61, 0x6c, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x18, 0x09, - 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x12, 0x21, 0x0a, - 0x07, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x07, - 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x07, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, - 0x42, 0x2a, 0x5a, 0x28, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, - 0x65, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x2f, 0x6c, 0x61, 0x6e, 0x74, 0x65, 0x72, - 0x6e, 0x2d, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2f, 0x70, 0x72, 0x6f, 0x62, 0x06, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x33, + 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x62, 0x65, 0x73, 0x74, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x62, 0x65, 0x73, 0x74, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x64, 0x50, 0x72, 0x69, 0x63, 0x65, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x75, 0x73, 0x64, 0x50, 0x72, 0x69, 0x63, 0x65, + 0x12, 0x26, 0x0a, 0x05, 0x70, 0x72, 0x69, 0x63, 0x65, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x10, 0x2e, 0x50, 0x6c, 0x61, 0x6e, 0x2e, 0x50, 0x72, 0x69, 0x63, 0x65, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x52, 0x05, 0x70, 0x72, 0x69, 0x63, 0x65, 0x12, 0x36, 0x0a, 0x16, 0x74, 0x6f, 0x74, 0x61, + 0x6c, 0x43, 0x6f, 0x73, 0x74, 0x42, 0x69, 0x6c, 0x6c, 0x65, 0x64, 0x4f, 0x6e, 0x65, 0x54, 0x69, + 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x16, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x43, + 0x6f, 0x73, 0x74, 0x42, 0x69, 0x6c, 0x6c, 0x65, 0x64, 0x4f, 0x6e, 0x65, 0x54, 0x69, 0x6d, 0x65, + 0x12, 0x22, 0x0a, 0x0c, 0x6f, 0x6e, 0x65, 0x4d, 0x6f, 0x6e, 0x74, 0x68, 0x43, 0x6f, 0x73, 0x74, + 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6f, 0x6e, 0x65, 0x4d, 0x6f, 0x6e, 0x74, 0x68, + 0x43, 0x6f, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x73, + 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x43, 0x6f, + 0x73, 0x74, 0x12, 0x26, 0x0a, 0x0e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x74, 0x65, 0x64, 0x42, + 0x6f, 0x6e, 0x75, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x66, 0x6f, 0x72, 0x6d, + 0x61, 0x74, 0x74, 0x65, 0x64, 0x42, 0x6f, 0x6e, 0x75, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x72, 0x65, + 0x6e, 0x65, 0x77, 0x61, 0x6c, 0x54, 0x65, 0x78, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0b, 0x72, 0x65, 0x6e, 0x65, 0x77, 0x61, 0x6c, 0x54, 0x65, 0x78, 0x74, 0x1a, 0x38, 0x0a, 0x0a, + 0x50, 0x72, 0x69, 0x63, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x2c, 0x0a, 0x0d, 0x50, 0x6c, 0x61, 0x6e, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1b, 0x0a, 0x05, 0x70, 0x6c, 0x61, 0x6e, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x05, 0x2e, 0x50, 0x6c, 0x61, 0x6e, 0x52, 0x05, 0x70, + 0x6c, 0x61, 0x6e, 0x73, 0x22, 0x46, 0x0a, 0x06, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x12, 0x0e, + 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, + 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x22, 0x9e, 0x02, 0x0a, + 0x13, 0x55, 0x73, 0x65, 0x72, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, + 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, + 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x66, 0x65, 0x72, 0x72, + 0x61, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x66, 0x65, 0x72, 0x72, + 0x61, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x1e, 0x0a, 0x0a, 0x75, 0x73, 0x65, 0x72, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x75, 0x73, + 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x6f, 0x63, 0x61, + 0x6c, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x65, + 0x12, 0x1e, 0x0a, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x08, + 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x18, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x07, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x12, 0x21, 0x0a, 0x07, 0x64, 0x65, + 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x07, 0x2e, 0x44, 0x65, + 0x76, 0x69, 0x63, 0x65, 0x52, 0x07, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x42, 0x2a, 0x5a, + 0x28, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x65, 0x74, 0x6c, + 0x61, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x2f, 0x6c, 0x61, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x2d, 0x63, + 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2f, 0x70, 0x72, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x33, } var ( @@ -614,7 +628,7 @@ func file_desktop_pro_pro_proto_rawDescGZIP() []byte { return file_desktop_pro_pro_proto_rawDescData } -var file_desktop_pro_pro_proto_msgTypes = make([]protoimpl.MessageInfo, 10) +var file_desktop_pro_pro_proto_msgTypes = make([]protoimpl.MessageInfo, 9) var file_desktop_pro_pro_proto_goTypes = []interface{}{ (*EmptyRequest)(nil), // 0: EmptyRequest (*EmptyResponse)(nil), // 1: EmptyResponse @@ -625,19 +639,16 @@ var file_desktop_pro_pro_proto_goTypes = []interface{}{ (*Device)(nil), // 6: Device (*UserDetailsResponse)(nil), // 7: UserDetailsResponse nil, // 8: Plan.PriceEntry - nil, // 9: Plan.ExpectedMonthlyPriceEntry } var file_desktop_pro_pro_proto_depIdxs = []int32{ - 3, // 0: Plan.duration:type_name -> Duration - 8, // 1: Plan.price:type_name -> Plan.PriceEntry - 9, // 2: Plan.expectedMonthlyPrice:type_name -> Plan.ExpectedMonthlyPriceEntry - 4, // 3: PlansResponse.plans:type_name -> Plan - 6, // 4: UserDetailsResponse.devices:type_name -> Device - 5, // [5:5] is the sub-list for method output_type - 5, // [5:5] is the sub-list for method input_type - 5, // [5:5] is the sub-list for extension type_name - 5, // [5:5] is the sub-list for extension extendee - 0, // [0:5] is the sub-list for field type_name + 8, // 0: Plan.price:type_name -> Plan.PriceEntry + 4, // 1: PlansResponse.plans:type_name -> Plan + 6, // 2: UserDetailsResponse.devices:type_name -> Device + 3, // [3:3] is the sub-list for method output_type + 3, // [3:3] is the sub-list for method input_type + 3, // [3:3] is the sub-list for extension type_name + 3, // [3:3] is the sub-list for extension extendee + 0, // [0:3] is the sub-list for field type_name } func init() { file_desktop_pro_pro_proto_init() } @@ -749,7 +760,7 @@ func file_desktop_pro_pro_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_desktop_pro_pro_proto_rawDesc, NumEnums: 0, - NumMessages: 10, + NumMessages: 9, NumExtensions: 0, NumServices: 0, }, diff --git a/desktop/pro/pro.proto b/desktop/pro/pro.proto index 75f5acb18..d5c910068 100644 --- a/desktop/pro/pro.proto +++ b/desktop/pro/pro.proto @@ -14,14 +14,16 @@ message Duration { } message Plan { - string id = 1; - string description = 2; - Duration duration = 3; - map price = 4; - map expectedMonthlyPrice = 5; - uint32 usdPrice = 6; - uint32 usdPrice1Y = 7; - uint32 usdPrice2Y = 8; + string id = 1; + string description = 2; + bool bestValue = 3; + int64 usdPrice = 4; + map price = 5; + string totalCostBilledOneTime = 6; + string oneMonthCost = 7; + string totalCost = 8; + string formattedBonus = 9; + string renewalText = 10; } message PlansResponse { diff --git a/lib/app_desktop.dart b/lib/app_desktop.dart deleted file mode 100644 index 8d5beea89..000000000 --- a/lib/app_desktop.dart +++ /dev/null @@ -1,54 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:lantern/account/account_tab.dart'; -import 'package:lantern/account/developer_settings.dart'; -import 'package:lantern/common/common.dart'; -import 'package:lantern/custom_bottom_bar.dart'; -import 'package:lantern/messaging/chats.dart'; -import 'package:lantern/messaging/onboarding/welcome.dart'; -import 'package:lantern/messaging/protos_flutteronly/messaging.pb.dart'; -import 'package:lantern/replica/replica_tab.dart'; -import 'package:lantern/vpn/try_lantern_chat.dart'; -import 'package:lantern/vpn/vpn_tab.dart'; -import 'package:logger/logger.dart'; -import 'package:lantern/core/router/router.dart'; - -final navigatorKey = GlobalKey(); -final globalRouter = AppRouter(); - -class DesktopApp extends StatefulWidget { - const DesktopApp({Key? key}) : super(key: key); - - @override - State createState() => _DesktopAppState(); -} - -class _DesktopAppState extends State { - @override - Widget build(BuildContext context) { - return MaterialApp.router( - title: 'Lantern Desktop'.i18n, - routeInformationParser: globalRouter.defaultRouteParser(), - routerDelegate: globalRouter.delegate(), - theme: ThemeData( - fontFamily: 'Roboto', - primarySwatch: Colors.blue, - ), - ); - } - - Widget buildBody(String selectedTab) { - switch (selectedTab) { - case TAB_VPN: - return VPNTab(); - case TAB_REPLICA: - return ReplicaTab(); - case TAB_ACCOUNT: - return AccountTab(); - case TAB_DEVELOPER: - return DeveloperSettingsTab(); - default: - assert(false, 'unrecognized tab $selectedTab'); - return Container(); - } - } -} diff --git a/lib/core/router/router.dart b/lib/core/router/router.dart index 69924f8bb..7b3c928cb 100644 --- a/lib/core/router/router.dart +++ b/lib/core/router/router.dart @@ -1,9 +1,8 @@ import 'package:auto_route/auto_route.dart'; +import 'package:lantern/common/common.dart'; import 'package:lantern/common/ui/transitions.dart'; import 'package:lantern/core/router/router.gr.dart'; - - @AutoRouterConfig( replaceInRouteName: 'Page,Route,Screen', ) @@ -12,7 +11,7 @@ class AppRouter extends $AppRouter { RouteType get defaultRouteType => const RouteType.adaptive(); @override final List routes = [ - AutoRoute(path: '/', page: Home.page), + AutoRoute(path: '/', page: Platform.isAndroid ? Home.page : DesktopHome.page), CustomRoute( page: FullScreenDialogPage.page, path: '/fullScreenDialogPage', @@ -157,6 +156,12 @@ class AppRouter extends $AppRouter { transitionsBuilder: defaultTransition, durationInMilliseconds: defaultTransitionMillis, reverseDurationInMilliseconds: defaultTransitionMillis), + CustomRoute( + page: PlansDesktop.page, + path: '/plansdesktop', + transitionsBuilder: defaultTransition, + durationInMilliseconds: defaultTransitionMillis, + reverseDurationInMilliseconds: defaultTransitionMillis), CustomRoute( page: ReplicaUploadTitle.page, path: '/replicaUploadTitle', diff --git a/lib/core/router/router.gr.dart b/lib/core/router/router.gr.dart index a7af9a6d8..806f33da8 100644 --- a/lib/core/router/router.gr.dart +++ b/lib/core/router/router.gr.dart @@ -8,10 +8,10 @@ // coverage:ignore-file // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:io' as _i45; +import 'dart:io' as _i47; -import 'package:auto_route/auto_route.dart' as _i41; -import 'package:flutter/cupertino.dart' as _i46; +import 'package:auto_route/auto_route.dart' as _i43; +import 'package:flutter/cupertino.dart' as _i48; import 'package:lantern/account/account.dart' as _i2; import 'package:lantern/account/account_management.dart' as _i1; import 'package:lantern/account/blocked_users.dart' as _i9; @@ -23,51 +23,53 @@ import 'package:lantern/account/device_linking/authorize_device_via_email.dart' as _i7; import 'package:lantern/account/device_linking/authorize_device_via_email_pin.dart' as _i8; -import 'package:lantern/account/device_linking/link_device.dart' as _i23; -import 'package:lantern/account/invite_friends.dart' as _i20; -import 'package:lantern/account/language.dart' as _i21; -import 'package:lantern/account/lantern_desktop.dart' as _i22; -import 'package:lantern/account/recovery_key.dart' as _i26; -import 'package:lantern/account/report_issue.dart' as _i35; -import 'package:lantern/account/settings.dart' as _i37; -import 'package:lantern/account/split_tunneling.dart' as _i38; -import 'package:lantern/account/support.dart' as _i40; -import 'package:lantern/common/common.dart' as _i43; +import 'package:lantern/account/device_linking/link_device.dart' as _i24; +import 'package:lantern/account/invite_friends.dart' as _i21; +import 'package:lantern/account/language.dart' as _i22; +import 'package:lantern/account/lantern_desktop.dart' as _i23; +import 'package:lantern/account/recovery_key.dart' as _i28; +import 'package:lantern/account/report_issue.dart' as _i37; +import 'package:lantern/account/settings.dart' as _i39; +import 'package:lantern/account/split_tunneling.dart' as _i40; +import 'package:lantern/account/support.dart' as _i42; +import 'package:lantern/common/common.dart' as _i45; import 'package:lantern/common/ui/app_webview.dart' as _i4; -import 'package:lantern/common/ui/full_screen_dialog.dart' as _i16; -import 'package:lantern/home.dart' as _i17; +import 'package:lantern/common/ui/full_screen_dialog.dart' as _i17; +import 'package:lantern/desktop/home.dart' as _i16; +import 'package:lantern/desktop/plans.dart' as _i26; +import 'package:lantern/home.dart' as _i18; import 'package:lantern/messaging/contacts/add_contact_number.dart' as _i3; import 'package:lantern/messaging/contacts/contact_info.dart' as _i14; -import 'package:lantern/messaging/contacts/new_chat.dart' as _i24; +import 'package:lantern/messaging/contacts/new_chat.dart' as _i25; import 'package:lantern/messaging/conversation/conversation.dart' as _i15; -import 'package:lantern/messaging/introductions/introduce.dart' as _i18; -import 'package:lantern/messaging/introductions/introductions.dart' as _i19; -import 'package:lantern/messaging/messaging.dart' as _i42; +import 'package:lantern/messaging/introductions/introduce.dart' as _i19; +import 'package:lantern/messaging/introductions/introductions.dart' as _i20; +import 'package:lantern/messaging/messaging.dart' as _i44; import 'package:lantern/messaging/onboarding/chat_number_messaging.dart' as _i11; import 'package:lantern/messaging/onboarding/chat_number_recovery.dart' as _i12; import 'package:lantern/plans/checkout.dart' as _i13; -import 'package:lantern/plans/plans.dart' as _i25; -import 'package:lantern/plans/reseller_checkout.dart' as _i36; -import 'package:lantern/plans/stripe_checkout.dart' as _i39; -import 'package:lantern/replica/common.dart' as _i44; -import 'package:lantern/replica/link_handler.dart' as _i29; -import 'package:lantern/replica/ui/viewers/audio.dart' as _i27; -import 'package:lantern/replica/ui/viewers/image.dart' as _i28; -import 'package:lantern/replica/ui/viewers/misc.dart' as _i30; -import 'package:lantern/replica/ui/viewers/video.dart' as _i34; -import 'package:lantern/replica/upload/description.dart' as _i31; -import 'package:lantern/replica/upload/review.dart' as _i32; -import 'package:lantern/replica/upload/title.dart' as _i33; - -abstract class $AppRouter extends _i41.RootStackRouter { +import 'package:lantern/plans/plans.dart' as _i27; +import 'package:lantern/plans/reseller_checkout.dart' as _i38; +import 'package:lantern/plans/stripe_checkout.dart' as _i41; +import 'package:lantern/replica/common.dart' as _i46; +import 'package:lantern/replica/link_handler.dart' as _i31; +import 'package:lantern/replica/ui/viewers/audio.dart' as _i29; +import 'package:lantern/replica/ui/viewers/image.dart' as _i30; +import 'package:lantern/replica/ui/viewers/misc.dart' as _i32; +import 'package:lantern/replica/ui/viewers/video.dart' as _i36; +import 'package:lantern/replica/upload/description.dart' as _i33; +import 'package:lantern/replica/upload/review.dart' as _i34; +import 'package:lantern/replica/upload/title.dart' as _i35; + +abstract class $AppRouter extends _i43.RootStackRouter { $AppRouter({super.navigatorKey}); @override - final Map pagesMap = { + final Map pagesMap = { AccountManagement.name: (routeData) { final args = routeData.argsAs(); - return _i41.AutoRoutePage( + return _i43.AutoRoutePage( routeData: routeData, child: _i1.AccountManagement( key: args.key, @@ -76,22 +78,20 @@ abstract class $AppRouter extends _i41.RootStackRouter { ); }, Account.name: (routeData) { - final args = - routeData.argsAs(orElse: () => const AccountArgs()); - return _i41.AutoRoutePage( + return _i43.AutoRoutePage( routeData: routeData, - child: _i2.AccountMenu(key: args.key), + child: const _i2.AccountMenu(), ); }, AddViaChatNumber.name: (routeData) { - return _i41.AutoRoutePage( + return _i43.AutoRoutePage( routeData: routeData, child: _i3.AddViaChatNumber(), ); }, AppWebview.name: (routeData) { final args = routeData.argsAs(); - return _i41.AutoRoutePage( + return _i43.AutoRoutePage( routeData: routeData, child: _i4.AppWebView( key: args.key, @@ -102,7 +102,7 @@ abstract class $AppRouter extends _i41.RootStackRouter { ApproveDevice.name: (routeData) { final args = routeData.argsAs( orElse: () => const ApproveDeviceArgs()); - return _i41.AutoRoutePage( + return _i43.AutoRoutePage( routeData: routeData, child: _i5.ApproveDevice(key: args.key), ); @@ -110,7 +110,7 @@ abstract class $AppRouter extends _i41.RootStackRouter { AuthorizePro.name: (routeData) { final args = routeData.argsAs( orElse: () => const AuthorizeProArgs()); - return _i41.AutoRoutePage( + return _i43.AutoRoutePage( routeData: routeData, child: _i6.AuthorizeDeviceForPro(key: args.key), ); @@ -118,7 +118,7 @@ abstract class $AppRouter extends _i41.RootStackRouter { AuthorizeDeviceEmail.name: (routeData) { final args = routeData.argsAs( orElse: () => const AuthorizeDeviceEmailArgs()); - return _i41.AutoRoutePage( + return _i43.AutoRoutePage( routeData: routeData, child: _i7.AuthorizeDeviceViaEmail(key: args.key), ); @@ -126,7 +126,7 @@ abstract class $AppRouter extends _i41.RootStackRouter { AuthorizeDeviceEmailPin.name: (routeData) { final args = routeData.argsAs( orElse: () => const AuthorizeDeviceEmailPinArgs()); - return _i41.AutoRoutePage( + return _i43.AutoRoutePage( routeData: routeData, child: _i8.AuthorizeDeviceViaEmailPin(key: args.key), ); @@ -134,32 +134,32 @@ abstract class $AppRouter extends _i41.RootStackRouter { BlockedUsers.name: (routeData) { final args = routeData.argsAs( orElse: () => const BlockedUsersArgs()); - return _i41.AutoRoutePage( + return _i43.AutoRoutePage( routeData: routeData, child: _i9.BlockedUsers(key: args.key), ); }, ChatNumberAccount.name: (routeData) { - return _i41.AutoRoutePage( + return _i43.AutoRoutePage( routeData: routeData, child: _i10.ChatNumberAccount(), ); }, ChatNumberMessaging.name: (routeData) { - return _i41.AutoRoutePage( + return _i43.AutoRoutePage( routeData: routeData, child: _i11.ChatNumberMessaging(), ); }, ChatNumberRecovery.name: (routeData) { - return _i41.AutoRoutePage( + return _i43.AutoRoutePage( routeData: routeData, child: _i12.ChatNumberRecovery(), ); }, Checkout.name: (routeData) { final args = routeData.argsAs(); - return _i41.AutoRoutePage( + return _i43.AutoRoutePage( routeData: routeData, child: _i13.Checkout( plan: args.plan, @@ -170,14 +170,14 @@ abstract class $AppRouter extends _i41.RootStackRouter { }, ContactInfo.name: (routeData) { final args = routeData.argsAs(); - return _i41.AutoRoutePage( + return _i43.AutoRoutePage( routeData: routeData, child: _i14.ContactInfo(contact: args.contact), ); }, Conversation.name: (routeData) { final args = routeData.argsAs(); - return _i41.AutoRoutePage( + return _i43.AutoRoutePage( routeData: routeData, child: _i15.Conversation( contactId: args.contactId, @@ -186,91 +186,105 @@ abstract class $AppRouter extends _i41.RootStackRouter { ), ); }, + DesktopHome.name: (routeData) { + return _i43.AutoRoutePage( + routeData: routeData, + child: const _i16.DesktopHomePage(), + ); + }, FullScreenDialogPage.name: (routeData) { final args = routeData.argsAs(); - return _i41.AutoRoutePage( + return _i43.AutoRoutePage( routeData: routeData, - child: _i16.FullScreenDialog( + child: _i17.FullScreenDialog( widget: args.widget, key: args.key, ), ); }, Home.name: (routeData) { - return _i41.AutoRoutePage( + return _i43.AutoRoutePage( routeData: routeData, - child: const _i17.HomePage(), + child: const _i18.HomePage(), ); }, Introduce.name: (routeData) { final args = routeData.argsAs(); - return _i41.AutoRoutePage( + return _i43.AutoRoutePage( routeData: routeData, - child: _i18.Introduce( + child: _i19.Introduce( singleIntro: args.singleIntro, contactToIntro: args.contactToIntro, ), ); }, Introductions.name: (routeData) { - return _i41.AutoRoutePage( + return _i43.AutoRoutePage( routeData: routeData, - child: _i19.Introductions(), + child: _i20.Introductions(), ); }, InviteFriends.name: (routeData) { - return _i41.AutoRoutePage( + return _i43.AutoRoutePage( routeData: routeData, - child: _i20.InviteFriends(), + child: _i21.InviteFriends(), ); }, Language.name: (routeData) { final args = routeData.argsAs(orElse: () => const LanguageArgs()); - return _i41.AutoRoutePage( + return _i43.AutoRoutePage( routeData: routeData, - child: _i21.Language(key: args.key), + child: _i22.Language(key: args.key), ); }, LanternDesktop.name: (routeData) { - return _i41.AutoRoutePage( + return _i43.AutoRoutePage( routeData: routeData, - child: const _i22.LanternDesktop(), + child: const _i23.LanternDesktop(), ); }, LinkDevice.name: (routeData) { final args = routeData.argsAs( orElse: () => const LinkDeviceArgs()); - return _i41.AutoRoutePage( + return _i43.AutoRoutePage( routeData: routeData, - child: _i23.LinkDevice(key: args.key), + child: _i24.LinkDevice(key: args.key), ); }, NewChat.name: (routeData) { - return _i41.AutoRoutePage( + return _i43.AutoRoutePage( + routeData: routeData, + child: _i25.NewChat(), + ); + }, + PlansDesktop.name: (routeData) { + final args = routeData.argsAs( + orElse: () => const PlansDesktopArgs()); + return _i43.AutoRoutePage( routeData: routeData, - child: _i24.NewChat(), + child: _i26.PlansDesktop(key: args.key), ); }, PlansPage.name: (routeData) { - return _i41.AutoRoutePage( + return _i43.AutoRoutePage( routeData: routeData, - child: _i25.PlansPage(), + child: _i27.PlansPage(), ); }, RecoveryKey.name: (routeData) { final args = routeData.argsAs( orElse: () => const RecoveryKeyArgs()); - return _i41.AutoRoutePage( + return _i43.AutoRoutePage( routeData: routeData, - child: _i26.RecoveryKey(key: args.key), + child: _i28.RecoveryKey(key: args.key), ); }, ReplicaAudioViewer.name: (routeData) { final args = routeData.argsAs(); - return _i41.AutoRoutePage( + return _i43.AutoRoutePage( routeData: routeData, - child: _i27.ReplicaAudioViewer( + child: _i29.ReplicaAudioViewer( replicaApi: args.replicaApi, item: args.item, category: args.category, @@ -279,9 +293,9 @@ abstract class $AppRouter extends _i41.RootStackRouter { }, ReplicaImageViewer.name: (routeData) { final args = routeData.argsAs(); - return _i41.AutoRoutePage( + return _i43.AutoRoutePage( routeData: routeData, - child: _i28.ReplicaImageViewer( + child: _i30.ReplicaImageViewer( replicaApi: args.replicaApi, item: args.item, category: args.category, @@ -290,9 +304,9 @@ abstract class $AppRouter extends _i41.RootStackRouter { }, ReplicaLinkHandler.name: (routeData) { final args = routeData.argsAs(); - return _i41.AutoRoutePage( + return _i43.AutoRoutePage( routeData: routeData, - child: _i29.ReplicaLinkHandler( + child: _i31.ReplicaLinkHandler( key: args.key, replicaApi: args.replicaApi, replicaLink: args.replicaLink, @@ -301,9 +315,9 @@ abstract class $AppRouter extends _i41.RootStackRouter { }, ReplicaMiscViewer.name: (routeData) { final args = routeData.argsAs(); - return _i41.AutoRoutePage( + return _i43.AutoRoutePage( routeData: routeData, - child: _i30.ReplicaMiscViewer( + child: _i32.ReplicaMiscViewer( replicaApi: args.replicaApi, item: args.item, category: args.category, @@ -312,9 +326,9 @@ abstract class $AppRouter extends _i41.RootStackRouter { }, ReplicaUploadDescription.name: (routeData) { final args = routeData.argsAs(); - return _i41.AutoRoutePage( + return _i43.AutoRoutePage( routeData: routeData, - child: _i31.ReplicaUploadDescription( + child: _i33.ReplicaUploadDescription( key: args.key, fileToUpload: args.fileToUpload, fileTitle: args.fileTitle, @@ -324,9 +338,9 @@ abstract class $AppRouter extends _i41.RootStackRouter { }, ReplicaUploadReview.name: (routeData) { final args = routeData.argsAs(); - return _i41.AutoRoutePage( + return _i43.AutoRoutePage( routeData: routeData, - child: _i32.ReplicaUploadReview( + child: _i34.ReplicaUploadReview( key: args.key, fileToUpload: args.fileToUpload, fileTitle: args.fileTitle, @@ -336,9 +350,9 @@ abstract class $AppRouter extends _i41.RootStackRouter { }, ReplicaUploadTitle.name: (routeData) { final args = routeData.argsAs(); - return _i41.AutoRoutePage( + return _i43.AutoRoutePage( routeData: routeData, - child: _i33.ReplicaUploadTitle( + child: _i35.ReplicaUploadTitle( key: args.key, fileToUpload: args.fileToUpload, fileTitle: args.fileTitle, @@ -348,9 +362,9 @@ abstract class $AppRouter extends _i41.RootStackRouter { }, ReplicaVideoViewer.name: (routeData) { final args = routeData.argsAs(); - return _i41.AutoRoutePage( + return _i43.AutoRoutePage( routeData: routeData, - child: _i34.ReplicaVideoViewer( + child: _i36.ReplicaVideoViewer( replicaApi: args.replicaApi, item: args.item, category: args.category, @@ -360,16 +374,16 @@ abstract class $AppRouter extends _i41.RootStackRouter { ReportIssue.name: (routeData) { final args = routeData.argsAs( orElse: () => const ReportIssueArgs()); - return _i41.AutoRoutePage( + return _i43.AutoRoutePage( routeData: routeData, - child: _i35.ReportIssue(key: args.key), + child: _i37.ReportIssue(key: args.key), ); }, ResellerCodeCheckout.name: (routeData) { final args = routeData.argsAs(); - return _i41.AutoRoutePage( + return _i43.AutoRoutePage( routeData: routeData, - child: _i36.ResellerCodeCheckout( + child: _i38.ResellerCodeCheckout( isPro: args.isPro, key: args.key, ), @@ -378,24 +392,24 @@ abstract class $AppRouter extends _i41.RootStackRouter { Settings.name: (routeData) { final args = routeData.argsAs(orElse: () => const SettingsArgs()); - return _i41.AutoRoutePage( + return _i43.AutoRoutePage( routeData: routeData, - child: _i37.Settings(key: args.key), + child: _i39.Settings(key: args.key), ); }, SplitTunneling.name: (routeData) { final args = routeData.argsAs( orElse: () => const SplitTunnelingArgs()); - return _i41.AutoRoutePage( + return _i43.AutoRoutePage( routeData: routeData, - child: _i38.SplitTunneling(key: args.key), + child: _i40.SplitTunneling(key: args.key), ); }, StripeCheckout.name: (routeData) { final args = routeData.argsAs(); - return _i41.AutoRoutePage( + return _i43.AutoRoutePage( routeData: routeData, - child: _i39.StripeCheckout( + child: _i41.StripeCheckout( plan: args.plan, email: args.email, refCode: args.refCode, @@ -405,9 +419,9 @@ abstract class $AppRouter extends _i41.RootStackRouter { ); }, Support.name: (routeData) { - return _i41.AutoRoutePage( + return _i43.AutoRoutePage( routeData: routeData, - child: const _i40.Support(), + child: const _i42.Support(), ); }, }; @@ -415,11 +429,11 @@ abstract class $AppRouter extends _i41.RootStackRouter { /// generated route for /// [_i1.AccountManagement] -class AccountManagement extends _i41.PageRouteInfo { +class AccountManagement extends _i43.PageRouteInfo { AccountManagement({ - _i42.Key? key, + _i44.Key? key, required bool isPro, - List<_i41.PageRouteInfo>? children, + List<_i43.PageRouteInfo>? children, }) : super( AccountManagement.name, args: AccountManagementArgs( @@ -431,8 +445,8 @@ class AccountManagement extends _i41.PageRouteInfo { static const String name = 'AccountManagement'; - static const _i41.PageInfo page = - _i41.PageInfo(name); + static const _i43.PageInfo page = + _i43.PageInfo(name); } class AccountManagementArgs { @@ -441,7 +455,7 @@ class AccountManagementArgs { required this.isPro, }); - final _i42.Key? key; + final _i44.Key? key; final bool isPro; @@ -453,37 +467,22 @@ class AccountManagementArgs { /// generated route for /// [_i2.AccountMenu] -class Account extends _i41.PageRouteInfo { - Account({ - _i43.Key? key, - List<_i41.PageRouteInfo>? children, - }) : super( +class Account extends _i43.PageRouteInfo { + const Account({List<_i43.PageRouteInfo>? children}) + : super( Account.name, - args: AccountArgs(key: key), initialChildren: children, ); static const String name = 'Account'; - static const _i41.PageInfo page = - _i41.PageInfo(name); -} - -class AccountArgs { - const AccountArgs({this.key}); - - final _i43.Key? key; - - @override - String toString() { - return 'AccountArgs{key: $key}'; - } + static const _i43.PageInfo page = _i43.PageInfo(name); } /// generated route for /// [_i3.AddViaChatNumber] -class AddViaChatNumber extends _i41.PageRouteInfo { - const AddViaChatNumber({List<_i41.PageRouteInfo>? children}) +class AddViaChatNumber extends _i43.PageRouteInfo { + const AddViaChatNumber({List<_i43.PageRouteInfo>? children}) : super( AddViaChatNumber.name, initialChildren: children, @@ -491,16 +490,16 @@ class AddViaChatNumber extends _i41.PageRouteInfo { static const String name = 'AddViaChatNumber'; - static const _i41.PageInfo page = _i41.PageInfo(name); + static const _i43.PageInfo page = _i43.PageInfo(name); } /// generated route for /// [_i4.AppWebView] -class AppWebview extends _i41.PageRouteInfo { +class AppWebview extends _i43.PageRouteInfo { AppWebview({ - _i43.Key? key, + _i45.Key? key, required String url, - List<_i41.PageRouteInfo>? children, + List<_i43.PageRouteInfo>? children, }) : super( AppWebview.name, args: AppWebviewArgs( @@ -512,8 +511,8 @@ class AppWebview extends _i41.PageRouteInfo { static const String name = 'AppWebview'; - static const _i41.PageInfo page = - _i41.PageInfo(name); + static const _i43.PageInfo page = + _i43.PageInfo(name); } class AppWebviewArgs { @@ -522,7 +521,7 @@ class AppWebviewArgs { required this.url, }); - final _i43.Key? key; + final _i45.Key? key; final String url; @@ -534,10 +533,10 @@ class AppWebviewArgs { /// generated route for /// [_i5.ApproveDevice] -class ApproveDevice extends _i41.PageRouteInfo { +class ApproveDevice extends _i43.PageRouteInfo { ApproveDevice({ - _i43.Key? key, - List<_i41.PageRouteInfo>? children, + _i45.Key? key, + List<_i43.PageRouteInfo>? children, }) : super( ApproveDevice.name, args: ApproveDeviceArgs(key: key), @@ -546,14 +545,14 @@ class ApproveDevice extends _i41.PageRouteInfo { static const String name = 'ApproveDevice'; - static const _i41.PageInfo page = - _i41.PageInfo(name); + static const _i43.PageInfo page = + _i43.PageInfo(name); } class ApproveDeviceArgs { const ApproveDeviceArgs({this.key}); - final _i43.Key? key; + final _i45.Key? key; @override String toString() { @@ -563,10 +562,10 @@ class ApproveDeviceArgs { /// generated route for /// [_i6.AuthorizeDeviceForPro] -class AuthorizePro extends _i41.PageRouteInfo { +class AuthorizePro extends _i43.PageRouteInfo { AuthorizePro({ - _i43.Key? key, - List<_i41.PageRouteInfo>? children, + _i45.Key? key, + List<_i43.PageRouteInfo>? children, }) : super( AuthorizePro.name, args: AuthorizeProArgs(key: key), @@ -575,14 +574,14 @@ class AuthorizePro extends _i41.PageRouteInfo { static const String name = 'AuthorizePro'; - static const _i41.PageInfo page = - _i41.PageInfo(name); + static const _i43.PageInfo page = + _i43.PageInfo(name); } class AuthorizeProArgs { const AuthorizeProArgs({this.key}); - final _i43.Key? key; + final _i45.Key? key; @override String toString() { @@ -593,10 +592,10 @@ class AuthorizeProArgs { /// generated route for /// [_i7.AuthorizeDeviceViaEmail] class AuthorizeDeviceEmail - extends _i41.PageRouteInfo { + extends _i43.PageRouteInfo { AuthorizeDeviceEmail({ - _i43.Key? key, - List<_i41.PageRouteInfo>? children, + _i45.Key? key, + List<_i43.PageRouteInfo>? children, }) : super( AuthorizeDeviceEmail.name, args: AuthorizeDeviceEmailArgs(key: key), @@ -605,14 +604,14 @@ class AuthorizeDeviceEmail static const String name = 'AuthorizeDeviceEmail'; - static const _i41.PageInfo page = - _i41.PageInfo(name); + static const _i43.PageInfo page = + _i43.PageInfo(name); } class AuthorizeDeviceEmailArgs { const AuthorizeDeviceEmailArgs({this.key}); - final _i43.Key? key; + final _i45.Key? key; @override String toString() { @@ -623,10 +622,10 @@ class AuthorizeDeviceEmailArgs { /// generated route for /// [_i8.AuthorizeDeviceViaEmailPin] class AuthorizeDeviceEmailPin - extends _i41.PageRouteInfo { + extends _i43.PageRouteInfo { AuthorizeDeviceEmailPin({ - _i43.Key? key, - List<_i41.PageRouteInfo>? children, + _i45.Key? key, + List<_i43.PageRouteInfo>? children, }) : super( AuthorizeDeviceEmailPin.name, args: AuthorizeDeviceEmailPinArgs(key: key), @@ -635,14 +634,14 @@ class AuthorizeDeviceEmailPin static const String name = 'AuthorizeDeviceEmailPin'; - static const _i41.PageInfo page = - _i41.PageInfo(name); + static const _i43.PageInfo page = + _i43.PageInfo(name); } class AuthorizeDeviceEmailPinArgs { const AuthorizeDeviceEmailPinArgs({this.key}); - final _i43.Key? key; + final _i45.Key? key; @override String toString() { @@ -652,10 +651,10 @@ class AuthorizeDeviceEmailPinArgs { /// generated route for /// [_i9.BlockedUsers] -class BlockedUsers extends _i41.PageRouteInfo { +class BlockedUsers extends _i43.PageRouteInfo { BlockedUsers({ - _i42.Key? key, - List<_i41.PageRouteInfo>? children, + _i44.Key? key, + List<_i43.PageRouteInfo>? children, }) : super( BlockedUsers.name, args: BlockedUsersArgs(key: key), @@ -664,14 +663,14 @@ class BlockedUsers extends _i41.PageRouteInfo { static const String name = 'BlockedUsers'; - static const _i41.PageInfo page = - _i41.PageInfo(name); + static const _i43.PageInfo page = + _i43.PageInfo(name); } class BlockedUsersArgs { const BlockedUsersArgs({this.key}); - final _i42.Key? key; + final _i44.Key? key; @override String toString() { @@ -681,8 +680,8 @@ class BlockedUsersArgs { /// generated route for /// [_i10.ChatNumberAccount] -class ChatNumberAccount extends _i41.PageRouteInfo { - const ChatNumberAccount({List<_i41.PageRouteInfo>? children}) +class ChatNumberAccount extends _i43.PageRouteInfo { + const ChatNumberAccount({List<_i43.PageRouteInfo>? children}) : super( ChatNumberAccount.name, initialChildren: children, @@ -690,13 +689,13 @@ class ChatNumberAccount extends _i41.PageRouteInfo { static const String name = 'ChatNumberAccount'; - static const _i41.PageInfo page = _i41.PageInfo(name); + static const _i43.PageInfo page = _i43.PageInfo(name); } /// generated route for /// [_i11.ChatNumberMessaging] -class ChatNumberMessaging extends _i41.PageRouteInfo { - const ChatNumberMessaging({List<_i41.PageRouteInfo>? children}) +class ChatNumberMessaging extends _i43.PageRouteInfo { + const ChatNumberMessaging({List<_i43.PageRouteInfo>? children}) : super( ChatNumberMessaging.name, initialChildren: children, @@ -704,13 +703,13 @@ class ChatNumberMessaging extends _i41.PageRouteInfo { static const String name = 'ChatNumberMessaging'; - static const _i41.PageInfo page = _i41.PageInfo(name); + static const _i43.PageInfo page = _i43.PageInfo(name); } /// generated route for /// [_i12.ChatNumberRecovery] -class ChatNumberRecovery extends _i41.PageRouteInfo { - const ChatNumberRecovery({List<_i41.PageRouteInfo>? children}) +class ChatNumberRecovery extends _i43.PageRouteInfo { + const ChatNumberRecovery({List<_i43.PageRouteInfo>? children}) : super( ChatNumberRecovery.name, initialChildren: children, @@ -718,17 +717,17 @@ class ChatNumberRecovery extends _i41.PageRouteInfo { static const String name = 'ChatNumberRecovery'; - static const _i41.PageInfo page = _i41.PageInfo(name); + static const _i43.PageInfo page = _i43.PageInfo(name); } /// generated route for /// [_i13.Checkout] -class Checkout extends _i41.PageRouteInfo { +class Checkout extends _i43.PageRouteInfo { Checkout({ - required _i43.Plan plan, + required _i45.Plan plan, required bool isPro, - _i43.Key? key, - List<_i41.PageRouteInfo>? children, + _i45.Key? key, + List<_i43.PageRouteInfo>? children, }) : super( Checkout.name, args: CheckoutArgs( @@ -741,8 +740,8 @@ class Checkout extends _i41.PageRouteInfo { static const String name = 'Checkout'; - static const _i41.PageInfo page = - _i41.PageInfo(name); + static const _i43.PageInfo page = + _i43.PageInfo(name); } class CheckoutArgs { @@ -752,11 +751,11 @@ class CheckoutArgs { this.key, }); - final _i43.Plan plan; + final _i45.Plan plan; final bool isPro; - final _i43.Key? key; + final _i45.Key? key; @override String toString() { @@ -766,10 +765,10 @@ class CheckoutArgs { /// generated route for /// [_i14.ContactInfo] -class ContactInfo extends _i41.PageRouteInfo { +class ContactInfo extends _i43.PageRouteInfo { ContactInfo({ - required _i42.Contact contact, - List<_i41.PageRouteInfo>? children, + required _i44.Contact contact, + List<_i43.PageRouteInfo>? children, }) : super( ContactInfo.name, args: ContactInfoArgs(contact: contact), @@ -778,14 +777,14 @@ class ContactInfo extends _i41.PageRouteInfo { static const String name = 'ContactInfo'; - static const _i41.PageInfo page = - _i41.PageInfo(name); + static const _i43.PageInfo page = + _i43.PageInfo(name); } class ContactInfoArgs { const ContactInfoArgs({required this.contact}); - final _i42.Contact contact; + final _i44.Contact contact; @override String toString() { @@ -795,12 +794,12 @@ class ContactInfoArgs { /// generated route for /// [_i15.Conversation] -class Conversation extends _i41.PageRouteInfo { +class Conversation extends _i43.PageRouteInfo { Conversation({ - required _i42.ContactId contactId, + required _i44.ContactId contactId, int? initialScrollIndex, bool showContactEditingDialog = false, - List<_i41.PageRouteInfo>? children, + List<_i43.PageRouteInfo>? children, }) : super( Conversation.name, args: ConversationArgs( @@ -813,8 +812,8 @@ class Conversation extends _i41.PageRouteInfo { static const String name = 'Conversation'; - static const _i41.PageInfo page = - _i41.PageInfo(name); + static const _i43.PageInfo page = + _i43.PageInfo(name); } class ConversationArgs { @@ -824,7 +823,7 @@ class ConversationArgs { this.showContactEditingDialog = false, }); - final _i42.ContactId contactId; + final _i44.ContactId contactId; final int? initialScrollIndex; @@ -837,13 +836,27 @@ class ConversationArgs { } /// generated route for -/// [_i16.FullScreenDialog] +/// [_i16.DesktopHomePage] +class DesktopHome extends _i43.PageRouteInfo { + const DesktopHome({List<_i43.PageRouteInfo>? children}) + : super( + DesktopHome.name, + initialChildren: children, + ); + + static const String name = 'DesktopHome'; + + static const _i43.PageInfo page = _i43.PageInfo(name); +} + +/// generated route for +/// [_i17.FullScreenDialog] class FullScreenDialogPage - extends _i41.PageRouteInfo { + extends _i43.PageRouteInfo { FullScreenDialogPage({ - required _i43.Widget widget, - _i43.Key? key, - List<_i41.PageRouteInfo>? children, + required _i45.Widget widget, + _i45.Key? key, + List<_i43.PageRouteInfo>? children, }) : super( FullScreenDialogPage.name, args: FullScreenDialogPageArgs( @@ -855,8 +868,8 @@ class FullScreenDialogPage static const String name = 'FullScreenDialogPage'; - static const _i41.PageInfo page = - _i41.PageInfo(name); + static const _i43.PageInfo page = + _i43.PageInfo(name); } class FullScreenDialogPageArgs { @@ -865,9 +878,9 @@ class FullScreenDialogPageArgs { this.key, }); - final _i43.Widget widget; + final _i45.Widget widget; - final _i43.Key? key; + final _i45.Key? key; @override String toString() { @@ -876,9 +889,9 @@ class FullScreenDialogPageArgs { } /// generated route for -/// [_i17.HomePage] -class Home extends _i41.PageRouteInfo { - const Home({List<_i41.PageRouteInfo>? children}) +/// [_i18.HomePage] +class Home extends _i43.PageRouteInfo { + const Home({List<_i43.PageRouteInfo>? children}) : super( Home.name, initialChildren: children, @@ -886,16 +899,16 @@ class Home extends _i41.PageRouteInfo { static const String name = 'Home'; - static const _i41.PageInfo page = _i41.PageInfo(name); + static const _i43.PageInfo page = _i43.PageInfo(name); } /// generated route for -/// [_i18.Introduce] -class Introduce extends _i41.PageRouteInfo { +/// [_i19.Introduce] +class Introduce extends _i43.PageRouteInfo { Introduce({ required bool singleIntro, - _i42.Contact? contactToIntro, - List<_i41.PageRouteInfo>? children, + _i44.Contact? contactToIntro, + List<_i43.PageRouteInfo>? children, }) : super( Introduce.name, args: IntroduceArgs( @@ -907,8 +920,8 @@ class Introduce extends _i41.PageRouteInfo { static const String name = 'Introduce'; - static const _i41.PageInfo page = - _i41.PageInfo(name); + static const _i43.PageInfo page = + _i43.PageInfo(name); } class IntroduceArgs { @@ -919,7 +932,7 @@ class IntroduceArgs { final bool singleIntro; - final _i42.Contact? contactToIntro; + final _i44.Contact? contactToIntro; @override String toString() { @@ -928,9 +941,9 @@ class IntroduceArgs { } /// generated route for -/// [_i19.Introductions] -class Introductions extends _i41.PageRouteInfo { - const Introductions({List<_i41.PageRouteInfo>? children}) +/// [_i20.Introductions] +class Introductions extends _i43.PageRouteInfo { + const Introductions({List<_i43.PageRouteInfo>? children}) : super( Introductions.name, initialChildren: children, @@ -938,13 +951,13 @@ class Introductions extends _i41.PageRouteInfo { static const String name = 'Introductions'; - static const _i41.PageInfo page = _i41.PageInfo(name); + static const _i43.PageInfo page = _i43.PageInfo(name); } /// generated route for -/// [_i20.InviteFriends] -class InviteFriends extends _i41.PageRouteInfo { - const InviteFriends({List<_i41.PageRouteInfo>? children}) +/// [_i21.InviteFriends] +class InviteFriends extends _i43.PageRouteInfo { + const InviteFriends({List<_i43.PageRouteInfo>? children}) : super( InviteFriends.name, initialChildren: children, @@ -952,15 +965,15 @@ class InviteFriends extends _i41.PageRouteInfo { static const String name = 'InviteFriends'; - static const _i41.PageInfo page = _i41.PageInfo(name); + static const _i43.PageInfo page = _i43.PageInfo(name); } /// generated route for -/// [_i21.Language] -class Language extends _i41.PageRouteInfo { +/// [_i22.Language] +class Language extends _i43.PageRouteInfo { Language({ - _i43.Key? key, - List<_i41.PageRouteInfo>? children, + _i45.Key? key, + List<_i43.PageRouteInfo>? children, }) : super( Language.name, args: LanguageArgs(key: key), @@ -969,14 +982,14 @@ class Language extends _i41.PageRouteInfo { static const String name = 'Language'; - static const _i41.PageInfo page = - _i41.PageInfo(name); + static const _i43.PageInfo page = + _i43.PageInfo(name); } class LanguageArgs { const LanguageArgs({this.key}); - final _i43.Key? key; + final _i45.Key? key; @override String toString() { @@ -985,9 +998,9 @@ class LanguageArgs { } /// generated route for -/// [_i22.LanternDesktop] -class LanternDesktop extends _i41.PageRouteInfo { - const LanternDesktop({List<_i41.PageRouteInfo>? children}) +/// [_i23.LanternDesktop] +class LanternDesktop extends _i43.PageRouteInfo { + const LanternDesktop({List<_i43.PageRouteInfo>? children}) : super( LanternDesktop.name, initialChildren: children, @@ -995,15 +1008,15 @@ class LanternDesktop extends _i41.PageRouteInfo { static const String name = 'LanternDesktop'; - static const _i41.PageInfo page = _i41.PageInfo(name); + static const _i43.PageInfo page = _i43.PageInfo(name); } /// generated route for -/// [_i23.LinkDevice] -class LinkDevice extends _i41.PageRouteInfo { +/// [_i24.LinkDevice] +class LinkDevice extends _i43.PageRouteInfo { LinkDevice({ - _i43.Key? key, - List<_i41.PageRouteInfo>? children, + _i45.Key? key, + List<_i43.PageRouteInfo>? children, }) : super( LinkDevice.name, args: LinkDeviceArgs(key: key), @@ -1012,14 +1025,14 @@ class LinkDevice extends _i41.PageRouteInfo { static const String name = 'LinkDevice'; - static const _i41.PageInfo page = - _i41.PageInfo(name); + static const _i43.PageInfo page = + _i43.PageInfo(name); } class LinkDeviceArgs { const LinkDeviceArgs({this.key}); - final _i43.Key? key; + final _i45.Key? key; @override String toString() { @@ -1028,9 +1041,9 @@ class LinkDeviceArgs { } /// generated route for -/// [_i24.NewChat] -class NewChat extends _i41.PageRouteInfo { - const NewChat({List<_i41.PageRouteInfo>? children}) +/// [_i25.NewChat] +class NewChat extends _i43.PageRouteInfo { + const NewChat({List<_i43.PageRouteInfo>? children}) : super( NewChat.name, initialChildren: children, @@ -1038,13 +1051,42 @@ class NewChat extends _i41.PageRouteInfo { static const String name = 'NewChat'; - static const _i41.PageInfo page = _i41.PageInfo(name); + static const _i43.PageInfo page = _i43.PageInfo(name); +} + +/// generated route for +/// [_i26.PlansDesktop] +class PlansDesktop extends _i43.PageRouteInfo { + PlansDesktop({ + _i45.Key? key, + List<_i43.PageRouteInfo>? children, + }) : super( + PlansDesktop.name, + args: PlansDesktopArgs(key: key), + initialChildren: children, + ); + + static const String name = 'PlansDesktop'; + + static const _i43.PageInfo page = + _i43.PageInfo(name); +} + +class PlansDesktopArgs { + const PlansDesktopArgs({this.key}); + + final _i45.Key? key; + + @override + String toString() { + return 'PlansDesktopArgs{key: $key}'; + } } /// generated route for -/// [_i25.PlansPage] -class PlansPage extends _i41.PageRouteInfo { - const PlansPage({List<_i41.PageRouteInfo>? children}) +/// [_i27.PlansPage] +class PlansPage extends _i43.PageRouteInfo { + const PlansPage({List<_i43.PageRouteInfo>? children}) : super( PlansPage.name, initialChildren: children, @@ -1052,15 +1094,15 @@ class PlansPage extends _i41.PageRouteInfo { static const String name = 'PlansPage'; - static const _i41.PageInfo page = _i41.PageInfo(name); + static const _i43.PageInfo page = _i43.PageInfo(name); } /// generated route for -/// [_i26.RecoveryKey] -class RecoveryKey extends _i41.PageRouteInfo { +/// [_i28.RecoveryKey] +class RecoveryKey extends _i43.PageRouteInfo { RecoveryKey({ - _i42.Key? key, - List<_i41.PageRouteInfo>? children, + _i44.Key? key, + List<_i43.PageRouteInfo>? children, }) : super( RecoveryKey.name, args: RecoveryKeyArgs(key: key), @@ -1069,14 +1111,14 @@ class RecoveryKey extends _i41.PageRouteInfo { static const String name = 'RecoveryKey'; - static const _i41.PageInfo page = - _i41.PageInfo(name); + static const _i43.PageInfo page = + _i43.PageInfo(name); } class RecoveryKeyArgs { const RecoveryKeyArgs({this.key}); - final _i42.Key? key; + final _i44.Key? key; @override String toString() { @@ -1085,13 +1127,13 @@ class RecoveryKeyArgs { } /// generated route for -/// [_i27.ReplicaAudioViewer] -class ReplicaAudioViewer extends _i41.PageRouteInfo { +/// [_i29.ReplicaAudioViewer] +class ReplicaAudioViewer extends _i43.PageRouteInfo { ReplicaAudioViewer({ - required _i44.ReplicaApi replicaApi, - required _i44.ReplicaSearchItem item, - required _i44.SearchCategory category, - List<_i41.PageRouteInfo>? children, + required _i46.ReplicaApi replicaApi, + required _i46.ReplicaSearchItem item, + required _i46.SearchCategory category, + List<_i43.PageRouteInfo>? children, }) : super( ReplicaAudioViewer.name, args: ReplicaAudioViewerArgs( @@ -1104,8 +1146,8 @@ class ReplicaAudioViewer extends _i41.PageRouteInfo { static const String name = 'ReplicaAudioViewer'; - static const _i41.PageInfo page = - _i41.PageInfo(name); + static const _i43.PageInfo page = + _i43.PageInfo(name); } class ReplicaAudioViewerArgs { @@ -1115,11 +1157,11 @@ class ReplicaAudioViewerArgs { required this.category, }); - final _i44.ReplicaApi replicaApi; + final _i46.ReplicaApi replicaApi; - final _i44.ReplicaSearchItem item; + final _i46.ReplicaSearchItem item; - final _i44.SearchCategory category; + final _i46.SearchCategory category; @override String toString() { @@ -1128,13 +1170,13 @@ class ReplicaAudioViewerArgs { } /// generated route for -/// [_i28.ReplicaImageViewer] -class ReplicaImageViewer extends _i41.PageRouteInfo { +/// [_i30.ReplicaImageViewer] +class ReplicaImageViewer extends _i43.PageRouteInfo { ReplicaImageViewer({ - required _i44.ReplicaApi replicaApi, - required _i44.ReplicaSearchItem item, - required _i44.SearchCategory category, - List<_i41.PageRouteInfo>? children, + required _i46.ReplicaApi replicaApi, + required _i46.ReplicaSearchItem item, + required _i46.SearchCategory category, + List<_i43.PageRouteInfo>? children, }) : super( ReplicaImageViewer.name, args: ReplicaImageViewerArgs( @@ -1147,8 +1189,8 @@ class ReplicaImageViewer extends _i41.PageRouteInfo { static const String name = 'ReplicaImageViewer'; - static const _i41.PageInfo page = - _i41.PageInfo(name); + static const _i43.PageInfo page = + _i43.PageInfo(name); } class ReplicaImageViewerArgs { @@ -1158,11 +1200,11 @@ class ReplicaImageViewerArgs { required this.category, }); - final _i44.ReplicaApi replicaApi; + final _i46.ReplicaApi replicaApi; - final _i44.ReplicaSearchItem item; + final _i46.ReplicaSearchItem item; - final _i44.SearchCategory category; + final _i46.SearchCategory category; @override String toString() { @@ -1171,13 +1213,13 @@ class ReplicaImageViewerArgs { } /// generated route for -/// [_i29.ReplicaLinkHandler] -class ReplicaLinkHandler extends _i41.PageRouteInfo { +/// [_i31.ReplicaLinkHandler] +class ReplicaLinkHandler extends _i43.PageRouteInfo { ReplicaLinkHandler({ - _i43.Key? key, - required _i44.ReplicaApi replicaApi, - required _i44.ReplicaLink replicaLink, - List<_i41.PageRouteInfo>? children, + _i45.Key? key, + required _i46.ReplicaApi replicaApi, + required _i46.ReplicaLink replicaLink, + List<_i43.PageRouteInfo>? children, }) : super( ReplicaLinkHandler.name, args: ReplicaLinkHandlerArgs( @@ -1190,8 +1232,8 @@ class ReplicaLinkHandler extends _i41.PageRouteInfo { static const String name = 'ReplicaLinkHandler'; - static const _i41.PageInfo page = - _i41.PageInfo(name); + static const _i43.PageInfo page = + _i43.PageInfo(name); } class ReplicaLinkHandlerArgs { @@ -1201,11 +1243,11 @@ class ReplicaLinkHandlerArgs { required this.replicaLink, }); - final _i43.Key? key; + final _i45.Key? key; - final _i44.ReplicaApi replicaApi; + final _i46.ReplicaApi replicaApi; - final _i44.ReplicaLink replicaLink; + final _i46.ReplicaLink replicaLink; @override String toString() { @@ -1214,13 +1256,13 @@ class ReplicaLinkHandlerArgs { } /// generated route for -/// [_i30.ReplicaMiscViewer] -class ReplicaMiscViewer extends _i41.PageRouteInfo { +/// [_i32.ReplicaMiscViewer] +class ReplicaMiscViewer extends _i43.PageRouteInfo { ReplicaMiscViewer({ - required _i44.ReplicaApi replicaApi, - required _i44.ReplicaSearchItem item, - required _i44.SearchCategory category, - List<_i41.PageRouteInfo>? children, + required _i46.ReplicaApi replicaApi, + required _i46.ReplicaSearchItem item, + required _i46.SearchCategory category, + List<_i43.PageRouteInfo>? children, }) : super( ReplicaMiscViewer.name, args: ReplicaMiscViewerArgs( @@ -1233,8 +1275,8 @@ class ReplicaMiscViewer extends _i41.PageRouteInfo { static const String name = 'ReplicaMiscViewer'; - static const _i41.PageInfo page = - _i41.PageInfo(name); + static const _i43.PageInfo page = + _i43.PageInfo(name); } class ReplicaMiscViewerArgs { @@ -1244,11 +1286,11 @@ class ReplicaMiscViewerArgs { required this.category, }); - final _i44.ReplicaApi replicaApi; + final _i46.ReplicaApi replicaApi; - final _i44.ReplicaSearchItem item; + final _i46.ReplicaSearchItem item; - final _i44.SearchCategory category; + final _i46.SearchCategory category; @override String toString() { @@ -1257,15 +1299,15 @@ class ReplicaMiscViewerArgs { } /// generated route for -/// [_i31.ReplicaUploadDescription] +/// [_i33.ReplicaUploadDescription] class ReplicaUploadDescription - extends _i41.PageRouteInfo { + extends _i43.PageRouteInfo { ReplicaUploadDescription({ - _i43.Key? key, - required _i45.File fileToUpload, + _i45.Key? key, + required _i47.File fileToUpload, required String fileTitle, String? fileDescription, - List<_i41.PageRouteInfo>? children, + List<_i43.PageRouteInfo>? children, }) : super( ReplicaUploadDescription.name, args: ReplicaUploadDescriptionArgs( @@ -1279,8 +1321,8 @@ class ReplicaUploadDescription static const String name = 'ReplicaUploadDescription'; - static const _i41.PageInfo page = - _i41.PageInfo(name); + static const _i43.PageInfo page = + _i43.PageInfo(name); } class ReplicaUploadDescriptionArgs { @@ -1291,9 +1333,9 @@ class ReplicaUploadDescriptionArgs { this.fileDescription, }); - final _i43.Key? key; + final _i45.Key? key; - final _i45.File fileToUpload; + final _i47.File fileToUpload; final String fileTitle; @@ -1306,14 +1348,14 @@ class ReplicaUploadDescriptionArgs { } /// generated route for -/// [_i32.ReplicaUploadReview] -class ReplicaUploadReview extends _i41.PageRouteInfo { +/// [_i34.ReplicaUploadReview] +class ReplicaUploadReview extends _i43.PageRouteInfo { ReplicaUploadReview({ - _i43.Key? key, - required _i45.File fileToUpload, + _i45.Key? key, + required _i47.File fileToUpload, required String fileTitle, String? fileDescription, - List<_i41.PageRouteInfo>? children, + List<_i43.PageRouteInfo>? children, }) : super( ReplicaUploadReview.name, args: ReplicaUploadReviewArgs( @@ -1327,8 +1369,8 @@ class ReplicaUploadReview extends _i41.PageRouteInfo { static const String name = 'ReplicaUploadReview'; - static const _i41.PageInfo page = - _i41.PageInfo(name); + static const _i43.PageInfo page = + _i43.PageInfo(name); } class ReplicaUploadReviewArgs { @@ -1339,9 +1381,9 @@ class ReplicaUploadReviewArgs { this.fileDescription, }); - final _i43.Key? key; + final _i45.Key? key; - final _i45.File fileToUpload; + final _i47.File fileToUpload; final String fileTitle; @@ -1354,14 +1396,14 @@ class ReplicaUploadReviewArgs { } /// generated route for -/// [_i33.ReplicaUploadTitle] -class ReplicaUploadTitle extends _i41.PageRouteInfo { +/// [_i35.ReplicaUploadTitle] +class ReplicaUploadTitle extends _i43.PageRouteInfo { ReplicaUploadTitle({ - _i43.Key? key, - required _i45.File fileToUpload, + _i45.Key? key, + required _i47.File fileToUpload, String? fileTitle, String? fileDescription, - List<_i41.PageRouteInfo>? children, + List<_i43.PageRouteInfo>? children, }) : super( ReplicaUploadTitle.name, args: ReplicaUploadTitleArgs( @@ -1375,8 +1417,8 @@ class ReplicaUploadTitle extends _i41.PageRouteInfo { static const String name = 'ReplicaUploadTitle'; - static const _i41.PageInfo page = - _i41.PageInfo(name); + static const _i43.PageInfo page = + _i43.PageInfo(name); } class ReplicaUploadTitleArgs { @@ -1387,9 +1429,9 @@ class ReplicaUploadTitleArgs { this.fileDescription, }); - final _i43.Key? key; + final _i45.Key? key; - final _i45.File fileToUpload; + final _i47.File fileToUpload; final String? fileTitle; @@ -1402,13 +1444,13 @@ class ReplicaUploadTitleArgs { } /// generated route for -/// [_i34.ReplicaVideoViewer] -class ReplicaVideoViewer extends _i41.PageRouteInfo { +/// [_i36.ReplicaVideoViewer] +class ReplicaVideoViewer extends _i43.PageRouteInfo { ReplicaVideoViewer({ - required _i44.ReplicaApi replicaApi, - required _i44.ReplicaSearchItem item, - required _i44.SearchCategory category, - List<_i41.PageRouteInfo>? children, + required _i46.ReplicaApi replicaApi, + required _i46.ReplicaSearchItem item, + required _i46.SearchCategory category, + List<_i43.PageRouteInfo>? children, }) : super( ReplicaVideoViewer.name, args: ReplicaVideoViewerArgs( @@ -1421,8 +1463,8 @@ class ReplicaVideoViewer extends _i41.PageRouteInfo { static const String name = 'ReplicaVideoViewer'; - static const _i41.PageInfo page = - _i41.PageInfo(name); + static const _i43.PageInfo page = + _i43.PageInfo(name); } class ReplicaVideoViewerArgs { @@ -1432,11 +1474,11 @@ class ReplicaVideoViewerArgs { required this.category, }); - final _i44.ReplicaApi replicaApi; + final _i46.ReplicaApi replicaApi; - final _i44.ReplicaSearchItem item; + final _i46.ReplicaSearchItem item; - final _i44.SearchCategory category; + final _i46.SearchCategory category; @override String toString() { @@ -1445,11 +1487,11 @@ class ReplicaVideoViewerArgs { } /// generated route for -/// [_i35.ReportIssue] -class ReportIssue extends _i41.PageRouteInfo { +/// [_i37.ReportIssue] +class ReportIssue extends _i43.PageRouteInfo { ReportIssue({ - _i43.Key? key, - List<_i41.PageRouteInfo>? children, + _i45.Key? key, + List<_i43.PageRouteInfo>? children, }) : super( ReportIssue.name, args: ReportIssueArgs(key: key), @@ -1458,14 +1500,14 @@ class ReportIssue extends _i41.PageRouteInfo { static const String name = 'ReportIssue'; - static const _i41.PageInfo page = - _i41.PageInfo(name); + static const _i43.PageInfo page = + _i43.PageInfo(name); } class ReportIssueArgs { const ReportIssueArgs({this.key}); - final _i43.Key? key; + final _i45.Key? key; @override String toString() { @@ -1474,13 +1516,13 @@ class ReportIssueArgs { } /// generated route for -/// [_i36.ResellerCodeCheckout] +/// [_i38.ResellerCodeCheckout] class ResellerCodeCheckout - extends _i41.PageRouteInfo { + extends _i43.PageRouteInfo { ResellerCodeCheckout({ required bool isPro, - _i43.Key? key, - List<_i41.PageRouteInfo>? children, + _i45.Key? key, + List<_i43.PageRouteInfo>? children, }) : super( ResellerCodeCheckout.name, args: ResellerCodeCheckoutArgs( @@ -1492,8 +1534,8 @@ class ResellerCodeCheckout static const String name = 'ResellerCodeCheckout'; - static const _i41.PageInfo page = - _i41.PageInfo(name); + static const _i43.PageInfo page = + _i43.PageInfo(name); } class ResellerCodeCheckoutArgs { @@ -1504,7 +1546,7 @@ class ResellerCodeCheckoutArgs { final bool isPro; - final _i43.Key? key; + final _i45.Key? key; @override String toString() { @@ -1513,11 +1555,11 @@ class ResellerCodeCheckoutArgs { } /// generated route for -/// [_i37.Settings] -class Settings extends _i41.PageRouteInfo { +/// [_i39.Settings] +class Settings extends _i43.PageRouteInfo { Settings({ - _i43.Key? key, - List<_i41.PageRouteInfo>? children, + _i45.Key? key, + List<_i43.PageRouteInfo>? children, }) : super( Settings.name, args: SettingsArgs(key: key), @@ -1526,14 +1568,14 @@ class Settings extends _i41.PageRouteInfo { static const String name = 'Settings'; - static const _i41.PageInfo page = - _i41.PageInfo(name); + static const _i43.PageInfo page = + _i43.PageInfo(name); } class SettingsArgs { const SettingsArgs({this.key}); - final _i43.Key? key; + final _i45.Key? key; @override String toString() { @@ -1542,11 +1584,11 @@ class SettingsArgs { } /// generated route for -/// [_i38.SplitTunneling] -class SplitTunneling extends _i41.PageRouteInfo { +/// [_i40.SplitTunneling] +class SplitTunneling extends _i43.PageRouteInfo { SplitTunneling({ - _i46.Key? key, - List<_i41.PageRouteInfo>? children, + _i48.Key? key, + List<_i43.PageRouteInfo>? children, }) : super( SplitTunneling.name, args: SplitTunnelingArgs(key: key), @@ -1555,14 +1597,14 @@ class SplitTunneling extends _i41.PageRouteInfo { static const String name = 'SplitTunneling'; - static const _i41.PageInfo page = - _i41.PageInfo(name); + static const _i43.PageInfo page = + _i43.PageInfo(name); } class SplitTunnelingArgs { const SplitTunnelingArgs({this.key}); - final _i46.Key? key; + final _i48.Key? key; @override String toString() { @@ -1571,15 +1613,15 @@ class SplitTunnelingArgs { } /// generated route for -/// [_i39.StripeCheckout] -class StripeCheckout extends _i41.PageRouteInfo { +/// [_i41.StripeCheckout] +class StripeCheckout extends _i43.PageRouteInfo { StripeCheckout({ - required _i43.Plan plan, + required _i45.Plan plan, required String email, String? refCode, required bool isPro, - _i43.Key? key, - List<_i41.PageRouteInfo>? children, + _i45.Key? key, + List<_i43.PageRouteInfo>? children, }) : super( StripeCheckout.name, args: StripeCheckoutArgs( @@ -1594,8 +1636,8 @@ class StripeCheckout extends _i41.PageRouteInfo { static const String name = 'StripeCheckout'; - static const _i41.PageInfo page = - _i41.PageInfo(name); + static const _i43.PageInfo page = + _i43.PageInfo(name); } class StripeCheckoutArgs { @@ -1607,7 +1649,7 @@ class StripeCheckoutArgs { this.key, }); - final _i43.Plan plan; + final _i45.Plan plan; final String email; @@ -1615,7 +1657,7 @@ class StripeCheckoutArgs { final bool isPro; - final _i43.Key? key; + final _i45.Key? key; @override String toString() { @@ -1624,9 +1666,9 @@ class StripeCheckoutArgs { } /// generated route for -/// [_i40.Support] -class Support extends _i41.PageRouteInfo { - const Support({List<_i41.PageRouteInfo>? children}) +/// [_i42.Support] +class Support extends _i43.PageRouteInfo { + const Support({List<_i43.PageRouteInfo>? children}) : super( Support.name, initialChildren: children, @@ -1634,5 +1676,5 @@ class Support extends _i41.PageRouteInfo { static const String name = 'Support'; - static const _i41.PageInfo page = _i41.PageInfo(name); + static const _i43.PageInfo page = _i43.PageInfo(name); } diff --git a/lib/desktop/account.dart b/lib/desktop/account.dart new file mode 100644 index 000000000..2bfd60bf0 --- /dev/null +++ b/lib/desktop/account.dart @@ -0,0 +1,111 @@ +import 'package:lantern/common/common.dart'; +import 'package:lantern/messaging/messaging_model.dart'; + +@RoutePage(name: 'DesktopAccount') +class AccountMenu extends StatelessWidget { + const AccountMenu({Key? key}) : super(key: key); + + Future authorizeDeviceForPro(BuildContext context) async => + await context.pushRoute(AuthorizePro()); + + void inviteFriends(BuildContext context) async => + await context.pushRoute(InviteFriends()); + + void openDesktopVersion(BuildContext context) async => + await context.pushRoute(LanternDesktop()); + + void openSettings(BuildContext context) => context.pushRoute(Settings()); + + void openSupport(BuildContext context) { + context.pushRoute(const Support()); + } + + void upgradeToLanternPro(BuildContext context) async => + await context.pushRoute(const PlansPage()); + + List freeItems(BuildContext context, SessionModel sessionModel) { + return [ + ListItemFactory.settingsItem( + key: AppKeys.upgrade_lantern_pro, + icon: ImagePaths.pro_icon_black, + content: 'Upgrade to Lantern Pro'.i18n, + onTap: () { + upgradeToLanternPro(context); + }, + ), + ListItemFactory.settingsItem( + icon: ImagePaths.star, + content: 'Invite Friends'.i18n, + onTap: () { + inviteFriends(context); + }, + ), + ListItemFactory.settingsItem( + icon: ImagePaths.devices, + content: 'Authorize Device for Pro'.i18n, + onTap: () { + authorizeDeviceForPro(context); + }, + ), + ...commonItems(context) + ]; + } + + List proItems(BuildContext context) { + return [ + ListItemFactory.settingsItem( + icon: ImagePaths.star, + content: 'Invite Friends'.i18n, + onTap: () { + inviteFriends(context); + }, + ), + ListItemFactory.settingsItem( + icon: ImagePaths.devices, + content: 'add_device'.i18n, + onTap: () async => await context.pushRoute(ApproveDevice()), + ), + ...commonItems(context) + ]; + } + + List commonItems(BuildContext context) { + return [ + ListItemFactory.settingsItem( + icon: ImagePaths.desktop, + content: 'desktop_version'.i18n, + onTap: () { + openDesktopVersion(context); + }, + ), + ListItemFactory.settingsItem( + key: AppKeys.support, + icon: ImagePaths.support, + content: 'support'.i18n, + onTap: () { + openSupport(context); + }, + ), + ListItemFactory.settingsItem( + icon: ImagePaths.settings, + content: 'settings'.i18n, + onTap: () { + openSettings(context); + }, + ), + ]; + } + + @override + Widget build(BuildContext context) { + bool proUser = false; + return BaseScreen( + title: 'Account'.i18n, + body: ListView( + children: proUser + ? proItems(context) + : freeItems(context, sessionModel), + ), + ); + } +} diff --git a/lib/desktop/account_tab.dart b/lib/desktop/account_tab.dart new file mode 100644 index 000000000..149af8abc --- /dev/null +++ b/lib/desktop/account_tab.dart @@ -0,0 +1,9 @@ +import 'package:flutter/cupertino.dart'; +import 'package:lantern/common/common.dart'; + +import 'account.dart'; + +class AccountTab extends StatelessWidget { + @override + Widget build(BuildContext context) => AccountMenu(); +} diff --git a/lib/desktop/app.dart b/lib/desktop/app.dart new file mode 100644 index 000000000..d2cf493c3 --- /dev/null +++ b/lib/desktop/app.dart @@ -0,0 +1,117 @@ +import 'package:flutter/material.dart'; +import 'package:lantern/account/account_tab.dart'; +import 'package:lantern/account/developer_settings.dart'; +import 'package:lantern/common/common.dart'; +import 'package:lantern/custom_bottom_bar.dart'; +import 'package:lantern/messaging/chats.dart'; +import 'package:lantern/messaging/onboarding/welcome.dart'; +import 'package:lantern/messaging/protos_flutteronly/messaging.pb.dart'; +import 'package:lantern/replica/replica_tab.dart'; +import 'package:lantern/vpn/try_lantern_chat.dart'; +import 'package:lantern/vpn/vpn_tab.dart'; +import 'package:logger/logger.dart'; +import 'package:lantern/core/router/router.dart'; + +final navigatorKey = GlobalKey(); +final globalRouter = AppRouter(); + +// This enum is used to manage the font families used in the application +enum AppFontFamily { + semim('Samim'), + roboto('Roboto'); + + // the actual string value (the font family name) to each enum value + const AppFontFamily(this.fontFamily); + + final String fontFamily; +} + +class DesktopApp extends StatefulWidget { + const DesktopApp({Key? key}) : super(key: key); + + @override + State createState() => _DesktopAppState(); +} + +class _DesktopAppState extends State { + + final translations = Localization.ensureInitialized(); + + @override + Widget build(BuildContext context) { + final currentLocal = View.of(context).platformDispatcher.locale; + return FutureBuilder( + future: translations, + builder: (BuildContext context, AsyncSnapshot snapshot) { + if (!snapshot.hasData) { + return Container(); + } + var lang = 'en'; + return GlobalLoaderOverlay( + overlayColor: Colors.black, + overlayOpacity: 0.6, + child: I18n( + initialLocale: currentLocale(lang), + child: MaterialApp.router( + locale: currentLocale(lang), + debugShowCheckedModeBanner: false, + theme: ThemeData( + fontFamily: _getLocaleBasedFont(currentLocal), + brightness: Brightness.light, + primarySwatch: Colors.grey, + appBarTheme: const AppBarTheme( + systemOverlayStyle: SystemUiOverlayStyle.dark, + ), + colorScheme: + ColorScheme.fromSwatch().copyWith(secondary: Colors.black), + ), + title: 'app_name'.i18n, + localizationsDelegates: const [ + GlobalMaterialLocalizations.delegate, + GlobalWidgetsLocalizations.delegate, + GlobalCupertinoLocalizations.delegate, + ], + routeInformationParser: globalRouter.defaultRouteParser(), + routerDelegate: globalRouter.delegate(), + supportedLocales: const [ + Locale('ar', 'EG'), + Locale('fr', 'FR'), + Locale('en', 'US'), + Locale('fa', 'IR'), + Locale('th', 'TH'), + Locale('ms', 'MY'), + Locale('ru', 'RU'), + Locale('ur', 'IN'), + Locale('zh', 'CN'), + Locale('zh', 'HK'), + Locale('es', 'ES'), + Locale('tr', 'TR'), + Locale('vi', 'VN'), + Locale('my', 'MM'), + ], + ), + ), + ); + }, + ); + } + + Locale currentLocale(String lang) { + if (lang == '' || lang.startsWith('en')) { + return const Locale('en', 'US'); + } + final codes = lang.split('_'); + return Locale(codes[0], codes[1]); + } + + String _getLocaleBasedFont(Locale locale) { + if (locale.languageCode == 'fa' || + locale.languageCode == 'ur' || + locale.languageCode == 'eg') { + return AppFontFamily.semim.fontFamily; // Farsi font + } else { + return AppFontFamily + .roboto.fontFamily; // Default font for other languages + } + } +} diff --git a/lib/desktop/custom_bottom_bar.dart b/lib/desktop/custom_bottom_bar.dart new file mode 100644 index 000000000..db63381b0 --- /dev/null +++ b/lib/desktop/custom_bottom_bar.dart @@ -0,0 +1,223 @@ +import 'package:lantern/desktop/custom_bottom_item.dart'; +import 'package:lantern/messaging/messaging.dart'; +import 'package:lantern/replica/common.dart'; + +class CustomBottomBar extends StatelessWidget { + final String selectedTab; + final bool isDevelop; + final bool isTesting; + + const CustomBottomBar({ + required this.selectedTab, + required this.isDevelop, + this.isTesting = false, + Key? key, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + + final indexToTab = {}; + final tabToIndex = {}; + + var nextIndex = 0; + indexToTab[nextIndex] = TAB_VPN; + tabToIndex[TAB_VPN] = nextIndex++; + indexToTab[nextIndex] = TAB_ACCOUNT; + tabToIndex[TAB_ACCOUNT] = nextIndex++; + if (isDevelop && !isTesting) { + indexToTab[nextIndex] = TAB_DEVELOPER; + tabToIndex[TAB_DEVELOPER] = nextIndex++; + } + + final currentIndex = tabToIndex[selectedTab] ?? tabToIndex[TAB_VPN]!; + return BottomNavigationBar( + currentIndex: currentIndex, + elevation: 0.0, + unselectedFontSize: 0, + selectedFontSize: 0, + showSelectedLabels: false, + type: BottomNavigationBarType.fixed, + items: buildItems( + indexToTab, + tabToIndex, + currentIndex, + false, + false, + true, + isDevelop, + isTesting, + "", + ), + ); + } + + List buildItems( + Map indexToTab, + Map tabToIndex, + int currentIndex, + bool chatEnabled, + bool replicaEnabled, + bool hasBeenOnboarded, + bool isDevelop, + bool isTesting, + String replicaAddr, + ) { + final items = []; + if (chatEnabled) { + items.add( + BottomNavigationBarItem( + icon: messagingModel.getFirstShownTryLanternChatModalTS( + (context, ts, _) => NowBuilder( + calculate: (now) => + hasBeenOnboarded != true && + (now.millisecondsSinceEpoch - ts) < oneWeekInMillis, + builder: (BuildContext context, bool showNewBadge) => + CustomBottomBarItem( + name: TAB_CHATS, + currentTabIndex: currentIndex, + indexToTab: indexToTab, + tabToIndex: tabToIndex, + label: 'chats'.i18n, + icon: ImagePaths.messages, + addBadge: (child) { + if (!chatEnabled || !showNewBadge) { + return messagingModel.contactsByActivity( + builder: ( + context, + Iterable> contacts, + Widget? _, + ) { + final totalUnviewed = contacts.isNotEmpty + ? contacts + .map( + (e) => e.value.isAccepted() + ? e.value.numUnviewedMessages + : 0, + ) + .reduce((value, element) => value + element) + : 0; + return CBadge( + showBadge: totalUnviewed > 0, + count: totalUnviewed, + child: child, + ); + }, + ); + } + + return CBadge( + end: -20, + top: -5, + showBadge: true, + customBadge: Container( + padding: const EdgeInsetsDirectional.only( + top: 2.0, + bottom: 2.0, + start: 5.0, + end: 5.0, + ), + decoration: BoxDecoration( + color: blue3, + borderRadius: const BorderRadius.all( + Radius.circular(80.0), + ), + ), + child: Text( + 'new'.i18n.toUpperCase(), + style: TextStyle( + fontSize: 10, + color: white, + ), + ), + ), + child: child, + ); + }, + ), + ), + ), + label: '', + tooltip: 'chats'.i18n, + ), + ); + } + + items.add( + BottomNavigationBarItem( + icon: CustomBottomBarItem( + name: TAB_VPN, + currentTabIndex: currentIndex, + indexToTab: indexToTab, + tabToIndex: tabToIndex, + label: 'VPN'.i18n, + icon: ImagePaths.key, + labelWidget: vpnModel.vpnStatus( + (context, value, child) => Padding( + padding: const EdgeInsetsDirectional.only(start: 4.0), + child: CircleAvatar( + maxRadius: activeIconSize - 4, + backgroundColor: (value.toLowerCase() == + 'Disconnecting'.i18n.toLowerCase() || + value == 'connected'.i18n.toLowerCase()) + ? indicatorGreen + : indicatorRed, + ), + ), + ), + ), + label: '', + tooltip: 'VPN'.i18n, + ), + ); + + items.add( + BottomNavigationBarItem( + icon: CustomBottomBarItem( + key: AppKeys.bottom_bar_account_tap_key, + name: TAB_ACCOUNT, + currentTabIndex: currentIndex, + indexToTab: indexToTab, + tabToIndex: tabToIndex, + label: 'Account'.i18n, + icon: ImagePaths.account, + addBadge: (child) { + if (hasBeenOnboarded != true) { + return child; + } + + return messagingModel.getCopiedRecoveryStatus( + (context, hasCopiedRecoveryKey, _) => CBadge( + count: 1, + showBadge: !hasCopiedRecoveryKey, + child: child, + ), + ); + }, + ), + label: '', + tooltip: 'Account'.i18n, + ), + ); + + if (isDevelop && !isTesting) { + items.add( + BottomNavigationBarItem( + icon: CustomBottomBarItem( + key: AppKeys.bottom_bar_developer_tap_key, + name: TAB_DEVELOPER, + currentTabIndex: currentIndex, + indexToTab: indexToTab, + tabToIndex: tabToIndex, + label: 'Developer'.i18n, + icon: ImagePaths.devices, + ), + label: '', + tooltip: 'Developer'.i18n, + ), + ); + } + + return items; + } +} diff --git a/lib/desktop/custom_bottom_item.dart b/lib/desktop/custom_bottom_item.dart new file mode 100644 index 000000000..7041f0b31 --- /dev/null +++ b/lib/desktop/custom_bottom_item.dart @@ -0,0 +1,147 @@ +import 'package:lantern/common/common.dart'; +import 'package:lantern/desktop/account_tab.dart'; +import 'package:lantern/desktop/ffi.dart'; +import 'dart:ffi' as ffi; // For FFI +import 'package:ffi/ffi.dart'; +import 'package:ffi/src/utf8.dart'; +import 'dart:convert'; + +class CustomBottomBarItem extends StatelessWidget { + const CustomBottomBarItem({ + required this.name, + required this.currentTabIndex, + required this.indexToTab, + required this.tabToIndex, + required this.icon, + required this.label, + this.labelWidget, + this.addBadge = defaultAddBadge, + Key? key, + }) : super(key: key); + + final String name; + final int currentTabIndex; + final Map indexToTab; + final Map tabToIndex; + final String label; + final String icon; + final Widget? labelWidget; + final Widget Function(Widget) addBadge; + + int get totalTabs => tabToIndex.length; + int get tabIndex => tabToIndex[name]!; + bool get active => currentTabIndex == tabIndex; + + static Widget defaultAddBadge(Widget child) => child; + + @override + Widget build(BuildContext context) { + return Container( + height: 68, + color: transparent, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Flexible( + fit: FlexFit.tight, + flex: 1, + child: CInkWell( + customBorder: RoundedRectangleBorder( + borderRadius: BorderRadiusDirectional.only( + topStart: Radius.circular( + currentTabIndex != 0 ? borderRadius : 0, + ), + topEnd: Radius.circular( + currentTabIndex != totalTabs ? borderRadius : 0, + ), + ), + ), + onTap: (() { + final tab = name.toNativeUtf8(); + setSelectTab(tab); + }), + child: Container( + decoration: ShapeDecoration( + color: tabIndex == currentTabIndex + ? selectedTabColor + : unselectedTabColor, + shape: CRoundedRectangleBorder( + topSide: tabIndex == currentTabIndex + ? null + : BorderSide( + color: borderColor, + width: 1, + ), + endSide: currentTabIndex == tabIndex + 1 + ? BorderSide( + color: borderColor, + width: 1, + ) + : null, + startSide: currentTabIndex == tabIndex - 1 + ? BorderSide( + color: borderColor, + width: 1, + ) + : null, + topStartCornerSide: BorderSide( + color: currentTabIndex == tabIndex - 1 + ? borderColor + : Colors.white, + ), + topEndCornerSide: BorderSide( + color: currentTabIndex == tabIndex + 1 + ? borderColor + : Colors.white, + ), + borderRadius: BorderRadiusDirectional.only( + topStart: Radius.circular( + currentTabIndex == tabIndex - 1 ? borderRadius : 0, + ), + topEnd: Radius.circular( + currentTabIndex == tabIndex + 1 ? borderRadius : 0, + ), + ), + ), + ), + child: Padding( + padding: const EdgeInsetsDirectional.only( + top: 12, + bottom: 12, + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: addBadge( + CAssetImage( + path: icon, + color: active + ? selectedTabIconColor + : unselectedTabIconColor, + ), + ), + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + CText( + label, + style: tsFloatingLabel.copiedWith( + color: active ? black : grey5, + ), + ), + labelWidget ?? const SizedBox(), + ], + ), + ], + ), + ), + ), + ), + ), + ], + ), + ); + } +} diff --git a/lib/ffi.dart b/lib/desktop/ffi.dart similarity index 68% rename from lib/ffi.dart rename to lib/desktop/ffi.dart index 2447b7383..5a642bc9a 100644 --- a/lib/ffi.dart +++ b/lib/desktop/ffi.dart @@ -12,6 +12,12 @@ typedef ProFunc = ffi.Pointer Function(); typedef sysproxy_func = ffi.Pointer Function(); // FFI fn signature typedef SysProxy = ffi.Pointer Function(); // Dart fn signature +typedef selecttab_func = ffi.Void Function(ffi.Pointer); +typedef SelectTab = void Function(ffi.Pointer); + +typedef selectedtab_func = ffi.Pointer Function(); // FFI fn signature +typedef SelectedTab = ffi.Pointer Function(); // Dart fn signature + final dylib = ffi.DynamicLibrary.open('liblantern.dylib'); final Start start = @@ -23,6 +29,12 @@ final SysProxy sysProxyOn = final SysProxy sysProxyOff = dylib.lookup>('SysProxyOff').asFunction(); +final SelectTab setSelectTab = + dylib.lookup>('SetSelectTab').asFunction(); + +final SelectedTab selectedTab = + dylib.lookup>('SelectedTab').asFunction(); + final ProFunc getPlans = dylib.lookup>('Plans').asFunction(); final ProFunc getUserData = dylib.lookup>('UserData').asFunction(); diff --git a/lib/desktop/home.dart b/lib/desktop/home.dart new file mode 100644 index 000000000..7f84050e1 --- /dev/null +++ b/lib/desktop/home.dart @@ -0,0 +1,55 @@ +import 'package:lantern/desktop/account_tab.dart'; +import 'package:lantern/account/developer_settings.dart'; +import 'package:lantern/account/privacy_disclosure.dart'; +import 'package:lantern/common/common.dart'; +import 'package:lantern/desktop/custom_bottom_bar.dart'; +import 'package:lantern/desktop/ffi.dart'; +import 'dart:ffi' as ffi; // For FFI +import 'package:ffi/ffi.dart'; +import 'package:ffi/src/utf8.dart'; +import 'package:lantern/replica/replica_tab.dart'; +import 'package:lantern/vpn/try_lantern_chat.dart'; +import 'package:lantern/vpn/vpn_tab.dart'; +import 'package:logger/logger.dart'; + +@RoutePage(name: 'DesktopHome') +class DesktopHomePage extends StatefulWidget { + const DesktopHomePage({Key? key}) : super(key: key); + + @override + _DesktopHomePageState createState() => _DesktopHomePageState(); +} + +class _DesktopHomePageState extends State { + BuildContext? _context; + + _DesktopHomePageState(); + + @override + Widget build(BuildContext context) { + return Scaffold( + body: buildBody(true), + bottomNavigationBar: CustomBottomBar( + selectedTab: TAB_VPN, + isDevelop: true, + isTesting: true, + ), + ); + } + + @override + Widget buildBody(bool isOnboarded) { + var tab = selectedTab().toDartString(); + switch (tab) { + case TAB_VPN: + return const VPNTab(); + case TAB_ACCOUNT: + return AccountTab(); + case TAB_DEVELOPER: + return DeveloperSettingsTab(); + default: + assert(false, 'unrecognized tab $selectedTab'); + return Container(); + } + } +} diff --git a/lib/main_desktop.dart b/lib/desktop/main.dart similarity index 79% rename from lib/main_desktop.dart rename to lib/desktop/main.dart index 7dd8bb934..6287f922a 100644 --- a/lib/main_desktop.dart +++ b/lib/desktop/main.dart @@ -2,9 +2,8 @@ import 'package:flutter/foundation.dart' show debugDefaultTargetPlatformOverride import 'package:flutter/material.dart'; import 'package:lantern/flutter_go.dart'; import 'package:flutter/services.dart'; -import 'package:lantern/app.dart'; -import 'package:lantern/app_desktop.dart'; -import 'package:lantern/ffi.dart'; +import 'package:lantern/desktop/app.dart'; +import 'package:lantern/desktop/ffi.dart'; import 'package:system_tray/system_tray.dart'; Future main() async { diff --git a/lib/desktop/plans.dart b/lib/desktop/plans.dart new file mode 100644 index 000000000..7d0f65eeb --- /dev/null +++ b/lib/desktop/plans.dart @@ -0,0 +1,216 @@ +import 'package:lantern/common/common.dart'; +import 'package:lantern/plans/plan_details.dart'; +import 'package:lantern/plans/utils.dart'; +import 'package:lantern/desktop/ffi.dart'; +import 'dart:ffi' as ffi; // For FFI +import 'package:ffi/ffi.dart'; +import 'package:ffi/src/utf8.dart'; +import 'dart:convert'; +import 'package:lantern/i18n/i18n.dart'; +import 'package:fixnum/fixnum.dart'; + +@RoutePage(name: "PlansDesktop") +class PlansDesktop extends StatefulWidget { + PlansDesktop({ + Key? key, + }) : super(key: key); + + @override + State createState() => _PlansDesktopState(); +} + +class _PlansDesktopState extends State + with SingleTickerProviderStateMixin { + List plans = []; + + @override + void initState() { + super.initState(); + WidgetsBinding.instance.addPostFrameCallback((_) { + fetchPlans(); + }); + } + + void fetchPlans() async { + var result = await getPlans().toDartString(); + setState(() { + var resp = jsonDecode(result) as List; + for (var item in resp) { + var plan = Plan(); + var usdPrice = item["usdPrice"]; + plan.id = item["id"]; + plan.description = item["description"]; + plan.bestValue = item["bestValue"] ?? false; + plan.usdPrice = Int64(item["usdPrice"]); + plan.oneMonthCost = "${usdPrice}"; + plans.add(plan); + } + }); + } + + @override + Widget build(BuildContext context) { + var proUser = false; + return FullScreenDialog( + widget: StatefulBuilder( + builder: (context, setState) => Container( + color: white, + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Expanded( + child: ListView( + shrinkWrap: true, + children: [ + Container( + padding: const EdgeInsetsDirectional.only( + top: 10, + bottom: 10, + start: 32, + end: 16, + ), + color: white, + child: Row( + children: [ + Container( + child: const CAssetImage( + path: ImagePaths.lantern_pro_logotype, + size: 20, + ), + ), + const Spacer(), + IconButton( + icon: mirrorLTR( + context: context, + child: CAssetImage( + path: ImagePaths.cancel, + color: black, + ), + ), + onPressed: () => Navigator.pop(context, null), + ), + ], + ), + ), + Container( + color: white, + padding: const EdgeInsetsDirectional.only( + start: 24, + end: 24, + ), + child: Column( + children: [ + // * Renewal text or upsell + if (proUser && plans.last.renewalText != '') + Padding( + padding: const EdgeInsetsDirectional.only( + bottom: 12.0, + ), + child: CText( + plans.last.renewalText, + style: tsBody1, + ), + ), + const Padding( + padding: EdgeInsetsDirectional.only( + bottom: 8.0, + ), + child: CDivider(), + ), + ...featuresList.map( + (feature) => Container( + padding: const EdgeInsetsDirectional.only( + start: 8, + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + const CAssetImage( + path: ImagePaths.check_green_large, + size: 24, + ), + Padding( + padding: const EdgeInsetsDirectional.only( + start: 4.0, + bottom: 4.0, + ), + child: CText( + feature, + textAlign: TextAlign.center, + style: tsBody1, + ), + ), + ], + ), + ), + ), + const CDivider(height: 24), + ], + ), + ), + // * Step + Container( + color: white, + padding: const EdgeInsetsDirectional.only( + top: 16.0, + bottom: 16.0, + start: 32.0, + end: 32.0, + ), + child: Container( + margin: const EdgeInsetsDirectional.only(start: 4.0), + child: PlanStep( + stepNum: '1', + description: 'choose_plan'.i18n, + ), + ), + ), + // * Card + ...plans.toList().reversed.map( + (plan) => Container( + color: white, + padding: const EdgeInsetsDirectional.only( + start: 32.0, + end: 32.0, + ), + child: PlanCard( + plan: plan as Plan, + isPro: proUser, + ), + ), + ), + ], + ), + ), + // * Footer + Padding( + padding: const EdgeInsetsDirectional.only(top: 24.0), + child: Container( + height: 40, + alignment: Alignment.center, + width: MediaQuery.of(context).size.width, + decoration: BoxDecoration( + border: Border( + top: BorderSide(width: 1.0, color: grey3), + ), + color: grey1, + ), + child: GestureDetector( + onTap: () async => await context.pushRoute( + ResellerCodeCheckout(isPro: proUser), + ), + child: CText( + 'Have a Lantern Pro activation code? Click here.', + style: tsBody1.copiedWith(color: grey5), + ), + ), // Translations + ), + ), + ], + ), + ), + )); + } +} diff --git a/lib/home.dart b/lib/home.dart index 42345a0f4..87de432f0 100644 --- a/lib/home.dart +++ b/lib/home.dart @@ -115,7 +115,7 @@ class _HomePageState extends State { super.dispose(); } - Widget build2(BuildContext context) { + Widget build(BuildContext context) { _context = context; return sessionModel.acceptedTermsVersion( (BuildContext context, int version, Widget? child) { @@ -144,7 +144,7 @@ class _HomePageState extends State { ).toLowerCase() == 'true'; return Scaffold( - //body: buildBody(selectedTab, isOnboarded), + body: buildBody(selectedTab, isOnboarded), bottomNavigationBar: CustomBottomBar( selectedTab: selectedTab, isDevelop: developmentMode, @@ -160,19 +160,7 @@ class _HomePageState extends State { } @override - Widget build(BuildContext context) { - return Scaffold( - body: buildBody(TAB_VPN, true), - bottomNavigationBar: CustomBottomBar( - selectedTab: TAB_VPN, - isDevelop: true, - isTesting: true, - ), - ); - } - - @override - Widget buildBody(String selectedTab, bool isOnboarded) { + Widget buildBody(String selectedTab, bool? isOnboarded) { switch (selectedTab) { case TAB_CHATS: return isOnboarded == null diff --git a/lib/i18n/i18n.dart b/lib/i18n/i18n.dart index d9a103fd0..b07597a24 100644 --- a/lib/i18n/i18n.dart +++ b/lib/i18n/i18n.dart @@ -26,6 +26,8 @@ extension Localization on String { static String get localeShort => locale.split('_')[0]; + String doLocalize() => localize(this, translations, locale: locale.replaceAll('_', '-')); + String get i18n => localize(this, translations, locale: locale.replaceAll('_', '-')); diff --git a/lib/plans/plans.dart b/lib/plans/plans.dart index 33fab230b..b95332914 100644 --- a/lib/plans/plans.dart +++ b/lib/plans/plans.dart @@ -1,181 +1,209 @@ import 'package:lantern/common/common.dart'; import 'package:lantern/plans/plan_details.dart'; -import 'dart:ffi' as ffi; // For FFI -import 'package:ffi/ffi.dart'; -import 'package:ffi/src/utf8.dart'; -import 'package:lantern/ffi.dart'; - -final featuresList = [ - 'unlimited_data'.i18n, - 'faster_data_centers'.i18n, - 'no_logs'.i18n, - 'connect_up_to_3_devices'.i18n, - 'no_ads'.i18n, -]; +import 'package:lantern/plans/utils.dart'; @RoutePage(name: "PlansPage") class PlansPage extends StatelessWidget { @override Widget build(BuildContext context) { - var proUser = false; - var plans = json.decode(getPlans().toDartString()); - print("${plans}"); return FullScreenDialog( - widget: StatefulBuilder( - builder: (context, setState) => Container( - color: white, - child: Column( - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Expanded( - child: ListView( - shrinkWrap: true, - children: [ - Container( - padding: const EdgeInsetsDirectional.only( - top: 10, - bottom: 10, - start: 32, - end: 16, - ), - color: white, - child: Row( - children: [ - Container( - child: const CAssetImage( - path: ImagePaths.lantern_pro_logotype, - size: 20, - ), - ), - const Spacer(), - IconButton( - icon: mirrorLTR( - context: context, - child: CAssetImage( - path: ImagePaths.cancel, - color: black, - ), - ), - onPressed: () => Navigator.pop(context, null), - ), - ], + widget: sessionModel + .proUser((BuildContext context, bool proUser, Widget? child) { + return sessionModel.plans( + builder: ( + context, + Iterable> plans, + Widget? child, + ) { + if (plans.isEmpty) { + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + CAssetImage( + path: ImagePaths.error, + size: 100, + color: grey5, ), - ), - Container( - color: white, - padding: const EdgeInsetsDirectional.only( - start: 24, - end: 24, + Padding( + padding: const EdgeInsetsDirectional.all(24.0), + child: CText( + 'error_fetching_plans'.i18n, + style: tsBody1, + ), ), - child: Column( - children: [ - // * Renewal text or upsell - if (proUser && plans.last.value.renewalText != '') - Padding( + ], + ), + ); + } + return StatefulBuilder( + builder: (context, setState) => Container( + color: white, + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Expanded( + child: ListView( + shrinkWrap: true, + children: [ + Container( padding: const EdgeInsetsDirectional.only( - bottom: 12.0, + top: 10, + bottom: 10, + start: 32, + end: 16, ), - child: CText( - plans.last.value.renewalText, - style: tsBody1, + color: white, + child: Row( + children: [ + Container( + child: const CAssetImage( + path: ImagePaths.lantern_pro_logotype, + size: 20, + ), + ), + const Spacer(), + IconButton( + icon: mirrorLTR( + context: context, + child: CAssetImage( + path: ImagePaths.cancel, + color: black, + ), + ), + onPressed: () => Navigator.pop(context, null), + ), + ], ), ), - const Padding( - padding: EdgeInsetsDirectional.only( - bottom: 8.0, - ), - child: CDivider(), - ), - ...featuresList.map( - (feature) => Container( + Container( + color: white, padding: const EdgeInsetsDirectional.only( - start: 8, + start: 24, + end: 24, ), - child: Row( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.start, + child: Column( children: [ - const CAssetImage( - path: ImagePaths.check_green_large, - size: 24, - ), - Padding( - padding: const EdgeInsetsDirectional.only( - start: 4.0, - bottom: 4.0, + // * Renewal text or upsell + if (proUser && + plans.last.value.renewalText != '') + Padding( + padding: const EdgeInsetsDirectional.only( + bottom: 12.0, + ), + child: CText( + plans.last.value.renewalText, + style: tsBody1, + ), ), - child: CText( - feature, - textAlign: TextAlign.center, - style: tsBody1, + const Padding( + padding: EdgeInsetsDirectional.only( + bottom: 8.0, ), + child: CDivider(), ), + ...featuresList.map( + (feature) => Container( + padding: const EdgeInsetsDirectional.only( + start: 8, + ), + child: Row( + crossAxisAlignment: + CrossAxisAlignment.center, + mainAxisAlignment: + MainAxisAlignment.start, + children: [ + const CAssetImage( + path: ImagePaths.check_green_large, + size: 24, + ), + Padding( + padding: + const EdgeInsetsDirectional.only( + start: 4.0, + bottom: 4.0, + ), + child: CText( + feature, + textAlign: TextAlign.center, + style: tsBody1, + ), + ), + ], + ), + ), + ), + const CDivider(height: 24), ], ), ), - ), - const CDivider(height: 24), - ], - ), - ), - // * Step - Container( - color: white, - padding: const EdgeInsetsDirectional.only( - top: 16.0, - bottom: 16.0, - start: 32.0, - end: 32.0, - ), - child: Container( - margin: const EdgeInsetsDirectional.only(start: 4.0), - child: PlanStep( - stepNum: '1', - description: 'choose_plan'.i18n, + // * Step + Container( + color: white, + padding: const EdgeInsetsDirectional.only( + top: 16.0, + bottom: 16.0, + start: 32.0, + end: 32.0, + ), + child: Container( + margin: + const EdgeInsetsDirectional.only(start: 4.0), + child: PlanStep( + stepNum: '1', + description: 'choose_plan'.i18n, + ), + ), + ), + // * Card + ...plans.toList().reversed.map( + (plan) => Container( + color: white, + padding: const EdgeInsetsDirectional.only( + start: 32.0, + end: 32.0, + ), + child: PlanCard( + plan: plan.value, + isPro: proUser, + ), + ), + ), + ], ), ), - ), - // * Card - ...plans.toList().reversed.map( - (plan) => Container( - color: white, - padding: const EdgeInsetsDirectional.only( - start: 32.0, - end: 32.0, + // * Footer + Padding( + padding: const EdgeInsetsDirectional.only(top: 24.0), + child: Container( + height: 40, + alignment: Alignment.center, + width: MediaQuery.of(context).size.width, + decoration: BoxDecoration( + border: Border( + top: BorderSide(width: 1.0, color: grey3), ), + color: grey1, ), + child: GestureDetector( + onTap: () async => await context.pushRoute( + ResellerCodeCheckout(isPro: proUser), + ), + child: CText( + 'Have a Lantern Pro activation code? Click here.', + style: tsBody1.copiedWith(color: grey5), + ), + ), // Translations ), - ], - ), - ), - // * Footer - Padding( - padding: const EdgeInsetsDirectional.only(top: 24.0), - child: Container( - height: 40, - alignment: Alignment.center, - width: MediaQuery.of(context).size.width, - decoration: BoxDecoration( - border: Border( - top: BorderSide(width: 1.0, color: grey3), - ), - color: grey1, + ), + ], ), - child: GestureDetector( - onTap: () async => await context.pushRoute( - ResellerCodeCheckout(isPro: proUser), - ), - child: CText( - 'Have a Lantern Pro activation code? Click here.', - style: tsBody1.copiedWith(color: grey5), - ), - ), // Translations ), - ), - ], - ), - ), - )); + ); + }, + ); + }), + ); } } diff --git a/lib/plans/utils.dart b/lib/plans/utils.dart index 204213adf..7472352fd 100644 --- a/lib/plans/utils.dart +++ b/lib/plans/utils.dart @@ -7,6 +7,14 @@ const lanternStarLogo = CAssetImage( size: 72, ); +final featuresList = [ + 'unlimited_data'.i18n, + 'faster_data_centers'.i18n, + 'no_logs'.i18n, + 'connect_up_to_3_devices'.i18n, + 'no_ads'.i18n, +]; + void onAPIcallTimeout({code, message}) { throw PlatformException( code: code, diff --git a/lib/vpn/vpn_pro_banner.dart b/lib/vpn/vpn_pro_banner.dart index 23b98dac2..37459c2d9 100644 --- a/lib/vpn/vpn_pro_banner.dart +++ b/lib/vpn/vpn_pro_banner.dart @@ -6,7 +6,7 @@ class ProBanner extends StatelessWidget { @override Widget build(BuildContext context) { return CInkWell( - onTap: () => context.pushRoute(const PlansPage()), + onTap: () => context.pushRoute(PlansDesktop()), child: Container( padding: const EdgeInsetsDirectional.all(16), decoration: BoxDecoration( diff --git a/lib/vpn/vpn_switch.dart b/lib/vpn/vpn_switch.dart index 6bc2d9b8e..3f174a377 100644 --- a/lib/vpn/vpn_switch.dart +++ b/lib/vpn/vpn_switch.dart @@ -1,5 +1,5 @@ import 'package:lantern/vpn/vpn.dart'; -import 'package:lantern/ffi.dart'; +import 'package:lantern/desktop/ffi.dart'; class VPNSwitch extends StatefulWidget { const VPNSwitch({super.key});