Line data Source code
1 : import 'package:cwtch/models/profile.dart';
2 : import 'package:cwtch/models/profileservers.dart';
3 : import 'package:cwtch/models/remoteserver.dart';
4 : import 'package:cwtch/models/servers.dart';
5 : import 'package:cwtch/widgets/remoteserverrow.dart';
6 : import 'package:flutter/material.dart';
7 : import 'package:flutter_gen/gen_l10n/app_localizations.dart';
8 : import 'package:provider/provider.dart';
9 :
10 : import '../cwtch_icons_icons.dart';
11 : import '../main.dart';
12 : import '../settings.dart';
13 :
14 : class ProfileServersView extends StatefulWidget {
15 0 : @override
16 0 : _ProfileServersView createState() => _ProfileServersView();
17 : }
18 :
19 : class _ProfileServersView extends State<ProfileServersView> {
20 0 : @override
21 : void dispose() {
22 0 : super.dispose();
23 : }
24 :
25 0 : @override
26 : Widget build(BuildContext context) {
27 0 : var knownServers = Provider.of<ProfileInfoState>(context).serverList.servers.map<String>((RemoteServerInfoState remoteServer) {
28 0 : return remoteServer.onion + ".onion";
29 0 : }).toSet();
30 0 : var importServerList = Provider.of<ServerListState>(context).servers.where((server) => !knownServers.contains(server.onion)).map<DropdownMenuItem<String>>((ServerInfoState serverInfo) {
31 0 : return DropdownMenuItem<String>(
32 0 : value: serverInfo.onion,
33 0 : child: Text(
34 0 : serverInfo.description.isNotEmpty ? serverInfo.description : serverInfo.onion,
35 : overflow: TextOverflow.ellipsis,
36 : ),
37 : );
38 0 : }).toList();
39 :
40 0 : importServerList.insert(0, DropdownMenuItem<String>(value: "", child: Text(AppLocalizations.of(context)!.importLocalServerSelectText)));
41 :
42 0 : return Scaffold(
43 0 : backgroundColor: Provider.of<Settings>(context, listen: false).theme.backgroundMainColor,
44 0 : appBar: AppBar(
45 0 : title: Text(MediaQuery.of(context).size.width > 600 ? AppLocalizations.of(context)!.manageKnownServersLong : AppLocalizations.of(context)!.manageKnownServersShort),
46 : ),
47 0 : body: Consumer<ProfileInfoState>(
48 0 : builder: (context, profile, child) {
49 0 : ProfileServerListState servers = profile.serverList;
50 0 : final tiles = servers.servers.map(
51 0 : (RemoteServerInfoState server) {
52 0 : return ChangeNotifierProvider<RemoteServerInfoState>.value(
53 : value: server,
54 0 : builder: (context, child) => RemoteServerRow(),
55 : );
56 : },
57 : );
58 :
59 0 : final divided = ListTile.divideTiles(
60 : context: context,
61 : tiles: tiles,
62 0 : ).toList();
63 :
64 0 : final importCard = Card(
65 0 : child: ListTile(
66 0 : title: Text(AppLocalizations.of(context)!.importLocalServerLabel),
67 0 : leading: Icon(CwtchIcons.add_circle_24px, color: Provider.of<Settings>(context).current().mainTextColor),
68 0 : trailing: DropdownButton(
69 0 : onChanged: (String? importServer) {
70 0 : if (importServer!.isNotEmpty) {
71 0 : var server = Provider.of<ServerListState>(context).getServer(importServer)!;
72 0 : showImportConfirm(context, profile.onion, server.onion, server.description, server.serverBundle);
73 : }
74 : },
75 : value: "",
76 : items: importServerList,
77 : )));
78 :
79 0 : return LayoutBuilder(builder: (BuildContext context, BoxConstraints viewportConstraints) {
80 0 : ScrollController controller = ScrollController();
81 0 : return Scrollbar(
82 : trackVisibility: true,
83 : controller: controller,
84 0 : child: SingleChildScrollView(
85 : clipBehavior: Clip.antiAlias,
86 : controller: controller,
87 0 : child: Container(
88 0 : margin: EdgeInsets.fromLTRB(5, 0, 5, 10),
89 0 : padding: EdgeInsets.fromLTRB(5, 0, 5, 10),
90 0 : child: Column(children: [if (importServerList.length > 1) importCard, Column(children: divided)]))));
91 : });
92 :
93 : return ListView(children: divided);
94 : },
95 : ));
96 : }
97 :
98 0 : showImportConfirm(BuildContext context, String profileHandle, String serverHandle, String serverDesc, String bundle) {
99 0 : var serverLabel = serverDesc.isNotEmpty ? serverDesc : serverHandle;
100 0 : serverHandle = serverHandle.substring(0, serverHandle.length - 6); // remove '.onion'
101 : // set up the buttons
102 0 : Widget cancelButton = ElevatedButton(
103 0 : child: Text(AppLocalizations.of(context)!.cancel),
104 0 : onPressed: () {
105 0 : Navigator.of(context).pop(); // dismiss dialog
106 : },
107 : );
108 0 : Widget continueButton = ElevatedButton(
109 0 : child: Text(AppLocalizations.of(context)!.importLocalServerButton.replaceAll("%1", serverLabel)),
110 0 : onPressed: () {
111 0 : Provider.of<FlwtchState>(context, listen: false).cwtch.ImportBundle(profileHandle, bundle);
112 : // Wait 500ms and hope the server is imported and add it's description in the UI and as an attribute
113 0 : Future.delayed(const Duration(milliseconds: 500), () {
114 0 : var profile = Provider.of<ProfileInfoState>(context);
115 0 : if (profile.serverList.getServer(serverHandle) != null) {
116 0 : profile.serverList.getServer(serverHandle)?.updateDescription(serverDesc);
117 :
118 0 : Provider.of<FlwtchState>(context, listen: false).cwtch.SetConversationAttribute(profile.onion, profile.serverList.getServer(serverHandle)!.identifier, "server.description", serverDesc);
119 : }
120 : });
121 0 : Navigator.of(context).pop();
122 : });
123 :
124 : // set up the AlertDialog
125 0 : AlertDialog alert = AlertDialog(
126 0 : title: Text(AppLocalizations.of(context)!.importLocalServerButton.replaceAll("%1", serverLabel)),
127 0 : actions: [
128 : cancelButton,
129 : continueButton,
130 : ],
131 : );
132 :
133 : // show the dialog
134 0 : showDialog(
135 : context: context,
136 0 : builder: (BuildContext context) {
137 : return alert;
138 : },
139 : );
140 : }
141 : }
|