Compare commits
2 Commits
4b6c7998f3
...
60985c6b37
Author | SHA1 | Date | |
---|---|---|---|
60985c6b37 | |||
a015399b57 |
@ -250,7 +250,10 @@
|
||||
"title": "About",
|
||||
"licensed": "Licensed under GPL3",
|
||||
"version": "Version ${version}",
|
||||
"viewSourceCode": "View source code"
|
||||
"viewSourceCode": "View source code",
|
||||
"nMoreToGo": "${n} more to go...",
|
||||
"debugMenuShown": "You are now a developer!",
|
||||
"debugMenuAlreadyShown": "You are already a developer!"
|
||||
},
|
||||
"appearance": {
|
||||
"title": "Appearance",
|
||||
|
@ -250,7 +250,10 @@
|
||||
"title": "Über",
|
||||
"licensed": "Lizensiert unter GPL3",
|
||||
"version": "Version ${version}",
|
||||
"viewSourceCode": "Quellcode anschauen"
|
||||
"viewSourceCode": "Quellcode anschauen",
|
||||
"nMoreToGo": "Noch ${n}...",
|
||||
"debugMenuShown": "Du bist jetzt ein Entwickler!",
|
||||
"debugMenuAlreadyShown": "Du bist bereits ein Entwickler!"
|
||||
},
|
||||
"appearance": {
|
||||
"title": "Aussehen",
|
||||
|
@ -1,4 +1,5 @@
|
||||
import 'package:moxxyv2/service/database/constants.dart';
|
||||
import 'package:moxxyv2/service/database/helpers.dart';
|
||||
import 'package:moxxyv2/shared/models/preference.dart';
|
||||
import 'package:sqflite_sqlcipher/sqflite.dart';
|
||||
|
||||
@ -427,4 +428,12 @@ Future<void> createDatabase(Database db, int version) async {
|
||||
'true',
|
||||
).toDatabaseJson(),
|
||||
);
|
||||
await db.insert(
|
||||
preferenceTable,
|
||||
Preference(
|
||||
'showDebugMenu',
|
||||
typeBool,
|
||||
boolToString(false),
|
||||
).toDatabaseJson(),
|
||||
);
|
||||
}
|
||||
|
@ -32,6 +32,7 @@ import 'package:moxxyv2/service/database/migrations/0000_stickers_missing_attrib
|
||||
import 'package:moxxyv2/service/database/migrations/0000_stickers_missing_attributes3.dart';
|
||||
import 'package:moxxyv2/service/database/migrations/0000_stickers_privacy.dart';
|
||||
import 'package:moxxyv2/service/database/migrations/0000_xmpp_state.dart';
|
||||
import 'package:moxxyv2/service/database/migrations/0001_debug_menu.dart';
|
||||
import 'package:moxxyv2/service/helpers.dart';
|
||||
import 'package:moxxyv2/service/not_specified.dart';
|
||||
import 'package:moxxyv2/service/omemo/omemo.dart';
|
||||
@ -82,7 +83,7 @@ class DatabaseService {
|
||||
_db = await openDatabase(
|
||||
dbPath,
|
||||
password: key,
|
||||
version: 25,
|
||||
version: 26,
|
||||
onCreate: createDatabase,
|
||||
onConfigure: (db) async {
|
||||
// In order to do schema changes during database upgrades, we disable foreign
|
||||
@ -191,6 +192,10 @@ class DatabaseService {
|
||||
_log.finest('Running migration for database version 25');
|
||||
await upgradeFromV24ToV25(db);
|
||||
}
|
||||
if (oldVersion < 26) {
|
||||
_log.finest('Running migration for database version 26');
|
||||
await upgradeFromV25ToV26(db);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
|
15
lib/service/database/migrations/0001_debug_menu.dart
Normal file
15
lib/service/database/migrations/0001_debug_menu.dart
Normal file
@ -0,0 +1,15 @@
|
||||
import 'package:moxxyv2/service/database/constants.dart';
|
||||
import 'package:moxxyv2/service/database/helpers.dart';
|
||||
import 'package:moxxyv2/shared/models/preference.dart';
|
||||
import 'package:sqflite_sqlcipher/sqflite.dart';
|
||||
|
||||
Future<void> upgradeFromV25ToV26(Database db) async {
|
||||
await db.insert(
|
||||
preferenceTable,
|
||||
Preference(
|
||||
'showDebugMenu',
|
||||
typeBool,
|
||||
boolToString(false),
|
||||
).toDatabaseJson(),
|
||||
);
|
||||
}
|
@ -32,6 +32,7 @@ class PreferencesState with _$PreferencesState {
|
||||
@Default(true) bool enableStickers,
|
||||
@Default(true) bool autoDownloadStickersFromContacts,
|
||||
@Default(true) bool isStickersNodePublic,
|
||||
@Default(false) bool showDebugMenu,
|
||||
}) = _PreferencesState;
|
||||
|
||||
// JSON serialization
|
||||
|
@ -1,11 +1,15 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:fluttertoast/fluttertoast.dart';
|
||||
import 'package:moxxyv2/i18n/strings.g.dart';
|
||||
import 'package:moxxyv2/shared/models/preferences.dart';
|
||||
import 'package:moxxyv2/ui/bloc/preferences_bloc.dart';
|
||||
import 'package:moxxyv2/ui/constants.dart';
|
||||
import 'package:moxxyv2/ui/widgets/topbar.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
// TODO(PapaTutuWawa): Include license text
|
||||
class SettingsAboutPage extends StatelessWidget {
|
||||
class SettingsAboutPage extends StatefulWidget {
|
||||
const SettingsAboutPage({ super.key });
|
||||
|
||||
static MaterialPageRoute<dynamic> get route => MaterialPageRoute<dynamic>(
|
||||
@ -14,7 +18,18 @@ class SettingsAboutPage extends StatelessWidget {
|
||||
name: aboutRoute,
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
@override
|
||||
SettingsAboutPageState createState() => SettingsAboutPageState();
|
||||
}
|
||||
|
||||
class SettingsAboutPageState extends State<SettingsAboutPage> {
|
||||
/// The amount of taps on the Moxxy logo, if showDebugMenu is false
|
||||
int _counter = 0;
|
||||
|
||||
/// True, if the toast ("You're already a developer") has already been shown once.
|
||||
bool _alreadyShownNotificationShown = false;
|
||||
|
||||
Future<void> _openUrl(String url) async {
|
||||
if (!await launchUrl(Uri.parse(url), mode: LaunchMode.externalApplication)) {
|
||||
// TODO(Unknown): Show a popup to copy the url
|
||||
@ -29,9 +44,45 @@ class SettingsAboutPage extends StatelessWidget {
|
||||
padding: const EdgeInsets.symmetric(horizontal: paddingVeryLarge),
|
||||
child: Column(
|
||||
children: [
|
||||
Image.asset(
|
||||
'assets/images/logo.png',
|
||||
width: 200, height: 200,
|
||||
BlocBuilder<PreferencesBloc, PreferencesState>(
|
||||
buildWhen: (prev, next) => prev.showDebugMenu != next.showDebugMenu,
|
||||
builder: (context, state) => InkWell(
|
||||
onTap: () async {
|
||||
if (state.showDebugMenu) {
|
||||
if (_counter == 0 && !_alreadyShownNotificationShown) {
|
||||
_alreadyShownNotificationShown = true;
|
||||
await Fluttertoast.showToast(
|
||||
msg: t.pages.settings.about.debugMenuAlreadyShown,
|
||||
gravity: ToastGravity.SNACKBAR,
|
||||
toastLength: Toast.LENGTH_SHORT,
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
_counter++;
|
||||
if (_counter == 10) {
|
||||
context.read<PreferencesBloc>().add(
|
||||
PreferencesChangedEvent(
|
||||
state.copyWith(
|
||||
showDebugMenu: true,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
await Fluttertoast.showToast(
|
||||
msg: t.pages.settings.about.debugMenuShown,
|
||||
gravity: ToastGravity.SNACKBAR,
|
||||
toastLength: Toast.LENGTH_SHORT,
|
||||
);
|
||||
}
|
||||
},
|
||||
child:Image.asset(
|
||||
'assets/images/logo.png',
|
||||
width: 200, height: 200,
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
t.global.title,
|
||||
|
@ -1,3 +1,4 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:moxxyv2/i18n/strings.g.dart';
|
||||
@ -135,6 +136,23 @@ class DebuggingPage extends StatelessWidget {
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
// Hide the testing commands outside of debug mode
|
||||
...kDebugMode ? [
|
||||
const SectionTitle('Testing'),
|
||||
SettingsRow(
|
||||
title: 'Reset showDebugMenu state',
|
||||
onTap: () {
|
||||
context.read<PreferencesBloc>().add(
|
||||
PreferencesChangedEvent(
|
||||
state.copyWith(
|
||||
showDebugMenu: false,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
] : [],
|
||||
],
|
||||
),
|
||||
),
|
||||
|
@ -1,7 +1,9 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:moxxyv2/i18n/strings.g.dart';
|
||||
import 'package:moxxyv2/shared/models/preferences.dart';
|
||||
import 'package:moxxyv2/ui/bloc/blocklist_bloc.dart';
|
||||
import 'package:moxxyv2/ui/bloc/preferences_bloc.dart';
|
||||
import 'package:moxxyv2/ui/constants.dart';
|
||||
@ -25,129 +27,132 @@ class SettingsPage extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: BorderlessTopbar.simple(t.pages.settings.settings.title),
|
||||
body: ListView(
|
||||
children: [
|
||||
SectionTitle(t.pages.settings.settings.conversationsSection),
|
||||
SettingsRow(
|
||||
title: t.pages.settings.settings.conversationsSection,
|
||||
prefix: const Padding(
|
||||
padding: EdgeInsets.only(right: 16),
|
||||
child: Icon(Icons.chat_bubble),
|
||||
),
|
||||
onTap: () {
|
||||
Navigator.pushNamed(context, conversationSettingsRoute);
|
||||
},
|
||||
),
|
||||
SettingsRow(
|
||||
title: t.pages.settings.stickers.title,
|
||||
prefix: const Padding(
|
||||
padding: EdgeInsets.only(right: 16),
|
||||
child: Icon(PhosphorIcons.stickerBold),
|
||||
),
|
||||
onTap: () {
|
||||
Navigator.pushNamed(context, stickersRoute);
|
||||
},
|
||||
),
|
||||
SettingsRow(
|
||||
title: t.pages.settings.network.title,
|
||||
prefix: const Padding(
|
||||
padding: EdgeInsets.only(right: 16),
|
||||
child: Icon(Icons.network_wifi),
|
||||
),
|
||||
onTap: () {
|
||||
Navigator.pushNamed(context, networkRoute);
|
||||
},
|
||||
),
|
||||
SettingsRow(
|
||||
title: t.pages.settings.privacy.title,
|
||||
prefix: const Padding(
|
||||
padding: EdgeInsets.only(right: 16),
|
||||
child: Icon(Icons.shield),
|
||||
),
|
||||
onTap: () {
|
||||
Navigator.pushNamed(context, privacyRoute);
|
||||
},
|
||||
),
|
||||
|
||||
SectionTitle(t.pages.settings.settings.accountSection),
|
||||
SettingsRow(
|
||||
title: t.pages.blocklist.title,
|
||||
prefix: const Padding(
|
||||
padding: EdgeInsets.only(right: 16),
|
||||
child: Icon(Icons.block),
|
||||
),
|
||||
onTap: () {
|
||||
GetIt.I.get<BlocklistBloc>().add(
|
||||
BlocklistRequestedEvent(),
|
||||
);
|
||||
},
|
||||
),
|
||||
SettingsRow(
|
||||
title: t.pages.settings.settings.signOut,
|
||||
prefix: const Padding(
|
||||
padding: EdgeInsets.only(right: 16),
|
||||
child: Icon(Icons.logout),
|
||||
),
|
||||
onTap: () async {
|
||||
final result = await showConfirmationDialog(
|
||||
t.pages.settings.settings.signOutConfirmTitle,
|
||||
t.pages.settings.settings.signOutConfirmBody,
|
||||
context,
|
||||
);
|
||||
|
||||
if (result) {
|
||||
GetIt.I.get<PreferencesBloc>().add(SignedOutEvent());
|
||||
}
|
||||
},
|
||||
),
|
||||
|
||||
SectionTitle(t.pages.settings.settings.miscellaneousSection),
|
||||
SettingsRow(
|
||||
title: t.pages.settings.appearance.title,
|
||||
prefix: const Padding(
|
||||
padding: EdgeInsets.only(right: 16),
|
||||
child: Icon(Icons.logout),
|
||||
),
|
||||
onTap: () {
|
||||
Navigator.pushNamed(context, appearanceRoute);
|
||||
},
|
||||
),
|
||||
SettingsRow(
|
||||
title: t.pages.settings.about.title,
|
||||
prefix: const Padding(
|
||||
padding: EdgeInsets.only(right: 16),
|
||||
child: Icon(Icons.info),
|
||||
),
|
||||
onTap: () {
|
||||
Navigator.pushNamed(context, aboutRoute);
|
||||
},
|
||||
),
|
||||
SettingsRow(
|
||||
title: t.pages.settings.licenses.title,
|
||||
prefix: const Padding(
|
||||
padding: EdgeInsets.only(right: 16),
|
||||
child: Icon(Icons.info),
|
||||
),
|
||||
onTap: () {
|
||||
Navigator.pushNamed(context, licensesRoute);
|
||||
},
|
||||
),
|
||||
|
||||
if (kDebugMode)
|
||||
SectionTitle(t.pages.settings.settings.debuggingSection),
|
||||
|
||||
if (kDebugMode)
|
||||
body: BlocBuilder<PreferencesBloc, PreferencesState>(
|
||||
buildWhen: (prev, next) => prev.showDebugMenu != next.showDebugMenu,
|
||||
builder: (context, state) => ListView(
|
||||
children: [
|
||||
SectionTitle(t.pages.settings.settings.conversationsSection),
|
||||
SettingsRow(
|
||||
title: t.pages.settings.debugging.title,
|
||||
title: t.pages.settings.settings.conversationsSection,
|
||||
prefix: const Padding(
|
||||
padding: EdgeInsets.only(right: 16),
|
||||
child: Icon(Icons.chat_bubble),
|
||||
),
|
||||
onTap: () {
|
||||
Navigator.pushNamed(context, conversationSettingsRoute);
|
||||
},
|
||||
),
|
||||
SettingsRow(
|
||||
title: t.pages.settings.stickers.title,
|
||||
prefix: const Padding(
|
||||
padding: EdgeInsets.only(right: 16),
|
||||
child: Icon(PhosphorIcons.stickerBold),
|
||||
),
|
||||
onTap: () {
|
||||
Navigator.pushNamed(context, stickersRoute);
|
||||
},
|
||||
),
|
||||
SettingsRow(
|
||||
title: t.pages.settings.network.title,
|
||||
prefix: const Padding(
|
||||
padding: EdgeInsets.only(right: 16),
|
||||
child: Icon(Icons.network_wifi),
|
||||
),
|
||||
onTap: () {
|
||||
Navigator.pushNamed(context, networkRoute);
|
||||
},
|
||||
),
|
||||
SettingsRow(
|
||||
title: t.pages.settings.privacy.title,
|
||||
prefix: const Padding(
|
||||
padding: EdgeInsets.only(right: 16),
|
||||
child: Icon(Icons.shield),
|
||||
),
|
||||
onTap: () {
|
||||
Navigator.pushNamed(context, privacyRoute);
|
||||
},
|
||||
),
|
||||
|
||||
SectionTitle(t.pages.settings.settings.accountSection),
|
||||
SettingsRow(
|
||||
title: t.pages.blocklist.title,
|
||||
prefix: const Padding(
|
||||
padding: EdgeInsets.only(right: 16),
|
||||
child: Icon(Icons.block),
|
||||
),
|
||||
onTap: () {
|
||||
GetIt.I.get<BlocklistBloc>().add(
|
||||
BlocklistRequestedEvent(),
|
||||
);
|
||||
},
|
||||
),
|
||||
SettingsRow(
|
||||
title: t.pages.settings.settings.signOut,
|
||||
prefix: const Padding(
|
||||
padding: EdgeInsets.only(right: 16),
|
||||
child: Icon(Icons.logout),
|
||||
),
|
||||
onTap: () async {
|
||||
final result = await showConfirmationDialog(
|
||||
t.pages.settings.settings.signOutConfirmTitle,
|
||||
t.pages.settings.settings.signOutConfirmBody,
|
||||
context,
|
||||
);
|
||||
|
||||
if (result) {
|
||||
GetIt.I.get<PreferencesBloc>().add(SignedOutEvent());
|
||||
}
|
||||
},
|
||||
),
|
||||
|
||||
SectionTitle(t.pages.settings.settings.miscellaneousSection),
|
||||
SettingsRow(
|
||||
title: t.pages.settings.appearance.title,
|
||||
prefix: const Padding(
|
||||
padding: EdgeInsets.only(right: 16),
|
||||
child: Icon(Icons.logout),
|
||||
),
|
||||
onTap: () {
|
||||
Navigator.pushNamed(context, appearanceRoute);
|
||||
},
|
||||
),
|
||||
SettingsRow(
|
||||
title: t.pages.settings.about.title,
|
||||
prefix: const Padding(
|
||||
padding: EdgeInsets.only(right: 16),
|
||||
child: Icon(Icons.info),
|
||||
),
|
||||
onTap: () {
|
||||
Navigator.pushNamed(context, debuggingRoute);
|
||||
Navigator.pushNamed(context, aboutRoute);
|
||||
},
|
||||
),
|
||||
],
|
||||
SettingsRow(
|
||||
title: t.pages.settings.licenses.title,
|
||||
prefix: const Padding(
|
||||
padding: EdgeInsets.only(right: 16),
|
||||
child: Icon(Icons.info),
|
||||
),
|
||||
onTap: () {
|
||||
Navigator.pushNamed(context, licensesRoute);
|
||||
},
|
||||
),
|
||||
|
||||
if (kDebugMode || state.showDebugMenu)
|
||||
SectionTitle(t.pages.settings.settings.debuggingSection),
|
||||
|
||||
if (kDebugMode || state.showDebugMenu)
|
||||
SettingsRow(
|
||||
title: t.pages.settings.debugging.title,
|
||||
prefix: const Padding(
|
||||
padding: EdgeInsets.only(right: 16),
|
||||
child: Icon(Icons.info),
|
||||
),
|
||||
onTap: () {
|
||||
Navigator.pushNamed(context, debuggingRoute);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user