mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-01-15 13:08:42 +00:00
fix #129
This commit is contained in:
parent
580dc3c3cf
commit
26af9460a6
14 changed files with 306 additions and 90 deletions
|
|
@ -84,6 +84,11 @@
|
||||||
"settingsTitle": "Einstellungen",
|
"settingsTitle": "Einstellungen",
|
||||||
"settingsChats": "Chats",
|
"settingsChats": "Chats",
|
||||||
"settingsStorageData": "Daten und Speicher",
|
"settingsStorageData": "Daten und Speicher",
|
||||||
|
"settingsStorageDataStoreInGTitle": "In der Galerie speichern",
|
||||||
|
"settingsStorageDataStoreInGSubtitle": "Speichere Bilder zusätzlich in der Systemgalerie.",
|
||||||
|
"settingsStorageDataMediaAutoDownload": "Automatischer Mediendownload",
|
||||||
|
"settingsStorageDataAutoDownMobile": "Bei Nutzung mobiler Daten",
|
||||||
|
"settingsStorageDataAutoDownWifi": "Bei Nutzung von WLAN",
|
||||||
"settingsPreSelectedReactions": "Vorgewählte Reaktions-Emojis",
|
"settingsPreSelectedReactions": "Vorgewählte Reaktions-Emojis",
|
||||||
"settingsPreSelectedReactionsError": "Es können maximal 12 Reaktionen ausgewählt werden.",
|
"settingsPreSelectedReactionsError": "Es können maximal 12 Reaktionen ausgewählt werden.",
|
||||||
"settingsProfile": "Profil",
|
"settingsProfile": "Profil",
|
||||||
|
|
|
||||||
|
|
@ -148,6 +148,16 @@
|
||||||
"@settingsProfile": {},
|
"@settingsProfile": {},
|
||||||
"settingsStorageData": "Data and storage",
|
"settingsStorageData": "Data and storage",
|
||||||
"@settingsStorageData": {},
|
"@settingsStorageData": {},
|
||||||
|
"settingsStorageDataStoreInGTitle": "Store in Gallery",
|
||||||
|
"@settingsStorageDataStoreInGTitle": {},
|
||||||
|
"settingsStorageDataStoreInGSubtitle": "Store saved images additional in the systems gallery.",
|
||||||
|
"@settingsStorageDataStoreInGSubtitle": {},
|
||||||
|
"settingsStorageDataMediaAutoDownload": "Media auto-download",
|
||||||
|
"@settingsStorageDataMediaAutoDownload": {},
|
||||||
|
"settingsStorageDataAutoDownMobile": "When using mobile data",
|
||||||
|
"@settingsStorageDataAutoDownMobile": {},
|
||||||
|
"settingsStorageDataAutoDownWifi": "When using WI-FI",
|
||||||
|
"@settingsStorageDataAutoDownWifi": {},
|
||||||
"settingsProfileCustomizeAvatar": "Customize your avatar",
|
"settingsProfileCustomizeAvatar": "Customize your avatar",
|
||||||
"@settingsProfileCustomizeAvatar": {},
|
"@settingsProfileCustomizeAvatar": {},
|
||||||
"settingsProfileEditDisplayName": "Displayname",
|
"settingsProfileEditDisplayName": "Displayname",
|
||||||
|
|
|
||||||
|
|
@ -527,6 +527,36 @@ abstract class AppLocalizations {
|
||||||
/// **'Data and storage'**
|
/// **'Data and storage'**
|
||||||
String get settingsStorageData;
|
String get settingsStorageData;
|
||||||
|
|
||||||
|
/// No description provided for @settingsStorageDataStoreInGTitle.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Store in Gallery'**
|
||||||
|
String get settingsStorageDataStoreInGTitle;
|
||||||
|
|
||||||
|
/// No description provided for @settingsStorageDataStoreInGSubtitle.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Store saved images additional in the systems gallery.'**
|
||||||
|
String get settingsStorageDataStoreInGSubtitle;
|
||||||
|
|
||||||
|
/// No description provided for @settingsStorageDataMediaAutoDownload.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Media auto-download'**
|
||||||
|
String get settingsStorageDataMediaAutoDownload;
|
||||||
|
|
||||||
|
/// No description provided for @settingsStorageDataAutoDownMobile.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'When using mobile data'**
|
||||||
|
String get settingsStorageDataAutoDownMobile;
|
||||||
|
|
||||||
|
/// No description provided for @settingsStorageDataAutoDownWifi.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'When using WI-FI'**
|
||||||
|
String get settingsStorageDataAutoDownWifi;
|
||||||
|
|
||||||
/// No description provided for @settingsProfileCustomizeAvatar.
|
/// No description provided for @settingsProfileCustomizeAvatar.
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
|
|
|
||||||
|
|
@ -226,6 +226,21 @@ class AppLocalizationsDe extends AppLocalizations {
|
||||||
@override
|
@override
|
||||||
String get settingsStorageData => 'Daten und Speicher';
|
String get settingsStorageData => 'Daten und Speicher';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsStorageDataStoreInGTitle => 'In der Galerie speichern';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsStorageDataStoreInGSubtitle => 'Speichere Bilder zusätzlich in der Systemgalerie.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsStorageDataMediaAutoDownload => 'Automatischer Mediendownload';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsStorageDataAutoDownMobile => 'Bei Nutzung mobiler Daten';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsStorageDataAutoDownWifi => 'Bei Nutzung von WLAN';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get settingsProfileCustomizeAvatar => 'Avatar anpassen';
|
String get settingsProfileCustomizeAvatar => 'Avatar anpassen';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -226,6 +226,21 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||||
@override
|
@override
|
||||||
String get settingsStorageData => 'Data and storage';
|
String get settingsStorageData => 'Data and storage';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsStorageDataStoreInGTitle => 'Store in Gallery';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsStorageDataStoreInGSubtitle => 'Store saved images additional in the systems gallery.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsStorageDataMediaAutoDownload => 'Media auto-download';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsStorageDataAutoDownMobile => 'When using mobile data';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsStorageDataAutoDownWifi => 'When using WI-FI';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get settingsProfileCustomizeAvatar => 'Customize your avatar';
|
String get settingsProfileCustomizeAvatar => 'Customize your avatar';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,8 @@ class UserData {
|
||||||
bool? useHighQuality;
|
bool? useHighQuality;
|
||||||
List<String>? preSelectedEmojies;
|
List<String>? preSelectedEmojies;
|
||||||
ThemeMode? themeMode;
|
ThemeMode? themeMode;
|
||||||
|
Map<String, List<String>>? autoDownloadOptions;
|
||||||
|
bool? storeMediaFilesInGallery;
|
||||||
|
|
||||||
final int userId;
|
final int userId;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,13 @@ UserData _$UserDataFromJson(Map<String, dynamic> json) => UserData(
|
||||||
..preSelectedEmojies = (json['preSelectedEmojies'] as List<dynamic>?)
|
..preSelectedEmojies = (json['preSelectedEmojies'] as List<dynamic>?)
|
||||||
?.map((e) => e as String)
|
?.map((e) => e as String)
|
||||||
.toList()
|
.toList()
|
||||||
..themeMode = $enumDecodeNullable(_$ThemeModeEnumMap, json['themeMode']);
|
..themeMode = $enumDecodeNullable(_$ThemeModeEnumMap, json['themeMode'])
|
||||||
|
..autoDownloadOptions =
|
||||||
|
(json['autoDownloadOptions'] as Map<String, dynamic>?)?.map(
|
||||||
|
(k, e) =>
|
||||||
|
MapEntry(k, (e as List<dynamic>).map((e) => e as String).toList()),
|
||||||
|
)
|
||||||
|
..storeMediaFilesInGallery = json['storeMediaFilesInGallery'] as bool?;
|
||||||
|
|
||||||
Map<String, dynamic> _$UserDataToJson(UserData instance) => <String, dynamic>{
|
Map<String, dynamic> _$UserDataToJson(UserData instance) => <String, dynamic>{
|
||||||
'username': instance.username,
|
'username': instance.username,
|
||||||
|
|
@ -31,6 +37,8 @@ Map<String, dynamic> _$UserDataToJson(UserData instance) => <String, dynamic>{
|
||||||
'useHighQuality': instance.useHighQuality,
|
'useHighQuality': instance.useHighQuality,
|
||||||
'preSelectedEmojies': instance.preSelectedEmojies,
|
'preSelectedEmojies': instance.preSelectedEmojies,
|
||||||
'themeMode': _$ThemeModeEnumMap[instance.themeMode],
|
'themeMode': _$ThemeModeEnumMap[instance.themeMode],
|
||||||
|
'autoDownloadOptions': instance.autoDownloadOptions,
|
||||||
|
'storeMediaFilesInGallery': instance.storeMediaFilesInGallery,
|
||||||
'userId': instance.userId,
|
'userId': instance.userId,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
import 'package:connectivity_plus/connectivity_plus.dart';
|
||||||
import 'package:drift/drift.dart';
|
import 'package:drift/drift.dart';
|
||||||
import 'package:path/path.dart';
|
import 'package:path/path.dart';
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
|
|
@ -8,7 +9,6 @@ import 'package:twonly/src/database/twonly_database.dart';
|
||||||
import 'package:twonly/src/database/tables/messages_table.dart';
|
import 'package:twonly/src/database/tables/messages_table.dart';
|
||||||
import 'package:twonly/src/model/json/message.dart';
|
import 'package:twonly/src/model/json/message.dart';
|
||||||
import 'package:twonly/src/providers/api/media_send.dart';
|
import 'package:twonly/src/providers/api/media_send.dart';
|
||||||
import 'package:twonly/src/utils/misc.dart';
|
|
||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
import 'package:cryptography_plus/cryptography_plus.dart';
|
import 'package:cryptography_plus/cryptography_plus.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
|
|
@ -17,6 +17,7 @@ import 'package:twonly/src/model/protobuf/api/client_to_server.pb.dart'
|
||||||
as client;
|
as client;
|
||||||
import 'package:twonly/src/model/protobuf/api/error.pb.dart';
|
import 'package:twonly/src/model/protobuf/api/error.pb.dart';
|
||||||
import 'package:twonly/src/model/protobuf/api/server_to_client.pbserver.dart';
|
import 'package:twonly/src/model/protobuf/api/server_to_client.pbserver.dart';
|
||||||
|
import 'package:twonly/src/utils/storage.dart';
|
||||||
|
|
||||||
Map<int, DateTime> downloadStartedForMediaReceived = {};
|
Map<int, DateTime> downloadStartedForMediaReceived = {};
|
||||||
|
|
||||||
|
|
@ -31,6 +32,51 @@ Future tryDownloadAllMediaFiles() async {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum DownloadMediaTypes {
|
||||||
|
video,
|
||||||
|
image,
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, List<String>> defaultAutoDownloadOptions = {
|
||||||
|
ConnectivityResult.mobile.name: [],
|
||||||
|
ConnectivityResult.wifi.name: [
|
||||||
|
DownloadMediaTypes.video.name,
|
||||||
|
DownloadMediaTypes.image.name
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
Future<bool> isAllowedToDownload(bool isVideo) async {
|
||||||
|
final List<ConnectivityResult> connectivityResult =
|
||||||
|
await (Connectivity().checkConnectivity());
|
||||||
|
|
||||||
|
final user = await getUser();
|
||||||
|
final options = user!.autoDownloadOptions ?? defaultAutoDownloadOptions;
|
||||||
|
|
||||||
|
if (connectivityResult.contains(ConnectivityResult.mobile)) {
|
||||||
|
if (isVideo) {
|
||||||
|
if (options[ConnectivityResult.mobile.name]!
|
||||||
|
.contains(DownloadMediaTypes.video.name)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else if (options[ConnectivityResult.mobile.name]!
|
||||||
|
.contains(DownloadMediaTypes.image.name)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (connectivityResult.contains(ConnectivityResult.wifi)) {
|
||||||
|
if (isVideo) {
|
||||||
|
if (options[ConnectivityResult.wifi.name]!
|
||||||
|
.contains(DownloadMediaTypes.video.name)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else if (options[ConnectivityResult.wifi.name]!
|
||||||
|
.contains(DownloadMediaTypes.image.name)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
Future startDownloadMedia(Message message, bool force) async {
|
Future startDownloadMedia(Message message, bool force) async {
|
||||||
if (message.contentJson == null) return;
|
if (message.contentJson == null) return;
|
||||||
if (downloadStartedForMediaReceived[message.messageId] != null) {
|
if (downloadStartedForMediaReceived[message.messageId] != null) {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
import 'package:connectivity_plus/connectivity_plus.dart';
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
|
@ -161,16 +160,6 @@ Future<bool> authenticateUser(String localizedReason,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> isAllowedToDownload(bool isVideo) async {
|
|
||||||
final List<ConnectivityResult> connectivityResult =
|
|
||||||
await (Connectivity().checkConnectivity());
|
|
||||||
if (connectivityResult.contains(ConnectivityResult.mobile)) {
|
|
||||||
Logger("tryDownloadMedia").info("abort download over mobile connection");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setupLogger() {
|
void setupLogger() {
|
||||||
Logger.root.level = kReleaseMode ? Level.INFO : Level.ALL;
|
Logger.root.level = kReleaseMode ? Level.INFO : Level.ALL;
|
||||||
Logger.root.onRecord.listen((record) async {
|
Logger.root.onRecord.listen((record) async {
|
||||||
|
|
|
||||||
|
|
@ -298,13 +298,14 @@ class _MediaViewerViewState extends State<MediaViewerView> {
|
||||||
setState(() {
|
setState(() {
|
||||||
imageSaved = true;
|
imageSaved = true;
|
||||||
});
|
});
|
||||||
final res = await saveImageToGallery(imageBytes!);
|
final user = await getUser();
|
||||||
if (res == null) {
|
if (user != null && (user.storeMediaFilesInGallery ?? true)) {
|
||||||
|
await saveImageToGallery(imageBytes!);
|
||||||
|
}
|
||||||
setState(() {
|
setState(() {
|
||||||
imageSaving = false;
|
imageSaving = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Widget bottomNavigation() {
|
Widget bottomNavigation() {
|
||||||
return Row(
|
return Row(
|
||||||
|
|
|
||||||
|
|
@ -7,15 +7,16 @@ class BetterListTile extends StatelessWidget {
|
||||||
final Widget? subtitle;
|
final Widget? subtitle;
|
||||||
final Color? color;
|
final Color? color;
|
||||||
final VoidCallback onTap;
|
final VoidCallback onTap;
|
||||||
|
final double iconSize;
|
||||||
|
|
||||||
const BetterListTile({
|
const BetterListTile(
|
||||||
super.key,
|
{super.key,
|
||||||
required this.icon,
|
required this.icon,
|
||||||
required this.text,
|
required this.text,
|
||||||
this.color,
|
this.color,
|
||||||
this.subtitle,
|
this.subtitle,
|
||||||
required this.onTap,
|
required this.onTap,
|
||||||
});
|
this.iconSize = 20});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
|
@ -27,7 +28,7 @@ class BetterListTile extends StatelessWidget {
|
||||||
),
|
),
|
||||||
child: FaIcon(
|
child: FaIcon(
|
||||||
icon,
|
icon,
|
||||||
size: 20,
|
size: iconSize,
|
||||||
color: color,
|
color: color,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -1,60 +1,58 @@
|
||||||
|
import 'package:connectivity_plus/connectivity_plus.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:twonly/src/providers/api/media_received.dart';
|
||||||
import 'package:twonly/src/views/components/better_list_title.dart';
|
import 'package:twonly/src/utils/storage.dart';
|
||||||
import 'package:twonly/src/views/components/better_text.dart';
|
|
||||||
import 'package:twonly/src/views/components/radio_button.dart';
|
|
||||||
import 'package:twonly/src/providers/settings_change_provider.dart';
|
|
||||||
import 'package:twonly/src/utils/misc.dart';
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
|
|
||||||
class DataAndStorageView extends StatelessWidget {
|
class DataAndStorageView extends StatefulWidget {
|
||||||
const DataAndStorageView({super.key});
|
const DataAndStorageView({super.key});
|
||||||
|
|
||||||
void _showSelectThemeMode(BuildContext context) async {
|
@override
|
||||||
ThemeMode? selectedValue = context.read<SettingsChangeProvider>().themeMode;
|
State<DataAndStorageView> createState() => _DataAndStorageViewState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _DataAndStorageViewState extends State<DataAndStorageView> {
|
||||||
|
Map<String, List<String>> autoDownloadOptions = defaultAutoDownloadOptions;
|
||||||
|
bool storeMediaFilesInGallery = true;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
initAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future initAsync() async {
|
||||||
|
final user = await getUser();
|
||||||
|
if (user == null) return;
|
||||||
|
setState(() {
|
||||||
|
autoDownloadOptions =
|
||||||
|
user.autoDownloadOptions ?? defaultAutoDownloadOptions;
|
||||||
|
storeMediaFilesInGallery = user.storeMediaFilesInGallery ?? true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void showAutoDownloadOptions(
|
||||||
|
BuildContext context, ConnectivityResult connectionMode) async {
|
||||||
await showDialog(
|
await showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
return AlertDialog(
|
return AutoDownloadOptionsDialog(
|
||||||
title: Text(context.lang.settingsAppearanceTheme),
|
autoDownloadOptions: autoDownloadOptions,
|
||||||
content: Column(
|
connectionMode: connectionMode,
|
||||||
mainAxisSize: MainAxisSize.min,
|
onUpdate: () async {
|
||||||
children: [
|
await initAsync();
|
||||||
RadioButton<ThemeMode>(
|
|
||||||
value: ThemeMode.system,
|
|
||||||
groupValue: selectedValue,
|
|
||||||
label: 'System default',
|
|
||||||
onChanged: (ThemeMode? value) {
|
|
||||||
selectedValue = value;
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
},
|
},
|
||||||
),
|
|
||||||
RadioButton<ThemeMode>(
|
|
||||||
value: ThemeMode.light,
|
|
||||||
groupValue: selectedValue,
|
|
||||||
label: 'Light',
|
|
||||||
onChanged: (ThemeMode? value) {
|
|
||||||
selectedValue = value;
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
RadioButton<ThemeMode>(
|
|
||||||
value: ThemeMode.dark,
|
|
||||||
groupValue: selectedValue,
|
|
||||||
label: 'Dark',
|
|
||||||
onChanged: (ThemeMode? value) {
|
|
||||||
selectedValue = value;
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
if (selectedValue != null && context.mounted) {
|
|
||||||
context.read<SettingsChangeProvider>().updateThemeMode(selectedValue);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void toggleStoreInGallery() async {
|
||||||
|
final user = await getUser();
|
||||||
|
if (user == null) return;
|
||||||
|
user.storeMediaFilesInGallery = !storeMediaFilesInGallery;
|
||||||
|
await updateUser(user);
|
||||||
|
initAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
@ -65,26 +63,40 @@ class DataAndStorageView extends StatelessWidget {
|
||||||
),
|
),
|
||||||
body: ListView(
|
body: ListView(
|
||||||
children: [
|
children: [
|
||||||
BetterText(text: "Media auto-download"),
|
|
||||||
ListTile(
|
ListTile(
|
||||||
title: Text("When using mobile data"),
|
title: Text(context.lang.settingsStorageDataStoreInGTitle),
|
||||||
subtitle: Text("Images", style: TextStyle(color: Colors.grey)),
|
subtitle: Text(context.lang.settingsStorageDataStoreInGSubtitle),
|
||||||
|
onTap: toggleStoreInGallery,
|
||||||
|
trailing: Checkbox(
|
||||||
|
value: storeMediaFilesInGallery,
|
||||||
|
onChanged: (a) => toggleStoreInGallery(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Divider(),
|
||||||
|
ListTile(
|
||||||
|
title: Text(
|
||||||
|
context.lang.settingsStorageDataMediaAutoDownload,
|
||||||
|
style: TextStyle(fontSize: 13),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
title: Text(context.lang.settingsStorageDataAutoDownMobile),
|
||||||
|
subtitle: Text(
|
||||||
|
autoDownloadOptions[ConnectivityResult.mobile.name]!.join(", "),
|
||||||
|
style: TextStyle(color: Colors.grey),
|
||||||
|
),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
_showSelectThemeMode(context);
|
showAutoDownloadOptions(context, ConnectivityResult.mobile);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
title: Text("When using Wi-Fi"),
|
title: Text(context.lang.settingsStorageDataAutoDownWifi),
|
||||||
subtitle: Text("Images", style: TextStyle(color: Colors.grey)),
|
subtitle: Text(
|
||||||
onTap: () {
|
autoDownloadOptions[ConnectivityResult.wifi.name]!.join(", "),
|
||||||
_showSelectThemeMode(context);
|
style: TextStyle(color: Colors.grey),
|
||||||
},
|
|
||||||
),
|
),
|
||||||
ListTile(
|
|
||||||
title: Text("When using roaming"),
|
|
||||||
subtitle: Text("Images", style: TextStyle(color: Colors.grey)),
|
|
||||||
onTap: () {
|
onTap: () {
|
||||||
_showSelectThemeMode(context);
|
showAutoDownloadOptions(context, ConnectivityResult.wifi);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
@ -92,3 +104,86 @@ class DataAndStorageView extends StatelessWidget {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class AutoDownloadOptionsDialog extends StatefulWidget {
|
||||||
|
final Map<String, List<String>> autoDownloadOptions;
|
||||||
|
final ConnectivityResult connectionMode;
|
||||||
|
final Function() onUpdate;
|
||||||
|
|
||||||
|
const AutoDownloadOptionsDialog({
|
||||||
|
super.key,
|
||||||
|
required this.autoDownloadOptions,
|
||||||
|
required this.connectionMode,
|
||||||
|
required this.onUpdate,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<AutoDownloadOptionsDialog> createState() =>
|
||||||
|
_AutoDownloadOptionsDialogState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _AutoDownloadOptionsDialogState extends State<AutoDownloadOptionsDialog> {
|
||||||
|
late Map<String, List<String>> autoDownloadOptions;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
autoDownloadOptions = widget.autoDownloadOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return AlertDialog(
|
||||||
|
title: Text(context.lang.settingsStorageDataMediaAutoDownload),
|
||||||
|
content: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
CheckboxListTile(
|
||||||
|
title: Text('Image'),
|
||||||
|
value: autoDownloadOptions[widget.connectionMode.name]!
|
||||||
|
.contains(DownloadMediaTypes.image.name),
|
||||||
|
onChanged: (bool? value) async {
|
||||||
|
await _updateAutoDownloadSetting(DownloadMediaTypes.image, value);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
CheckboxListTile(
|
||||||
|
title: Text('Video'),
|
||||||
|
value: autoDownloadOptions[widget.connectionMode.name]!
|
||||||
|
.contains(DownloadMediaTypes.video.name),
|
||||||
|
onChanged: (bool? value) async {
|
||||||
|
await _updateAutoDownloadSetting(DownloadMediaTypes.video, value);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
child: Text(context.lang.close),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _updateAutoDownloadSetting(
|
||||||
|
DownloadMediaTypes type, bool? value) async {
|
||||||
|
if (value == null) return;
|
||||||
|
|
||||||
|
// Update the autoDownloadOptions based on the checkbox state
|
||||||
|
autoDownloadOptions[widget.connectionMode.name]!
|
||||||
|
.removeWhere((element) => element == type.name);
|
||||||
|
if (value) {
|
||||||
|
autoDownloadOptions[widget.connectionMode.name]!.add(type.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the onUpdate callback to notify the parent widget
|
||||||
|
final user = await getUser();
|
||||||
|
if (user == null) return;
|
||||||
|
user.autoDownloadOptions = autoDownloadOptions;
|
||||||
|
await updateUser(user);
|
||||||
|
widget.onUpdate();
|
||||||
|
setState(() {});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,6 @@ class HelpView extends StatelessWidget {
|
||||||
FaIcon(FontAwesomeIcons.arrowUpRightFromSquare, size: 15),
|
FaIcon(FontAwesomeIcons.arrowUpRightFromSquare, size: 15),
|
||||||
),
|
),
|
||||||
Divider(),
|
Divider(),
|
||||||
|
|
||||||
FutureBuilder(
|
FutureBuilder(
|
||||||
future: PackageInfo.fromPlatform(),
|
future: PackageInfo.fromPlatform(),
|
||||||
builder: (context, snap) {
|
builder: (context, snap) {
|
||||||
|
|
@ -76,8 +75,6 @@ class HelpView extends StatelessWidget {
|
||||||
style: TextStyle(color: Colors.grey, fontSize: 13),
|
style: TextStyle(color: Colors.grey, fontSize: 13),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
//
|
|
||||||
],
|
],
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import 'package:twonly/src/utils/storage.dart';
|
||||||
import 'package:twonly/src/views/settings/account_view.dart';
|
import 'package:twonly/src/views/settings/account_view.dart';
|
||||||
import 'package:twonly/src/views/settings/appearance_view.dart';
|
import 'package:twonly/src/views/settings/appearance_view.dart';
|
||||||
import 'package:twonly/src/views/settings/chat/chat_settings_view.dart';
|
import 'package:twonly/src/views/settings/chat/chat_settings_view.dart';
|
||||||
|
import 'package:twonly/src/views/settings/data_and_storage_view.dart';
|
||||||
import 'package:twonly/src/views/settings/notification_view.dart';
|
import 'package:twonly/src/views/settings/notification_view.dart';
|
||||||
import 'package:twonly/src/views/settings/profile/profile_view.dart';
|
import 'package:twonly/src/views/settings/profile/profile_view.dart';
|
||||||
import 'package:twonly/src/views/settings/help_view.dart';
|
import 'package:twonly/src/views/settings/help_view.dart';
|
||||||
|
|
@ -153,11 +154,12 @@ class _SettingsMainViewState extends State<SettingsMainView> {
|
||||||
),
|
),
|
||||||
BetterListTile(
|
BetterListTile(
|
||||||
icon: FontAwesomeIcons.chartPie,
|
icon: FontAwesomeIcons.chartPie,
|
||||||
|
iconSize: 15,
|
||||||
text: context.lang.settingsStorageData,
|
text: context.lang.settingsStorageData,
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
Navigator.push(context,
|
Navigator.push(context,
|
||||||
MaterialPageRoute(builder: (context) {
|
MaterialPageRoute(builder: (context) {
|
||||||
return NotificationView();
|
return DataAndStorageView();
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue