finished theme sharing

This commit is contained in:
Kima 2023-09-08 23:15:56 +02:00
parent 070e3cf18c
commit 67721112cc
10 changed files with 257 additions and 67 deletions

View File

@ -0,0 +1,14 @@
// This is a generated file; do not edit or check into version control.
FLUTTER_ROOT=/Users/kima/src/flutter
FLUTTER_APPLICATION_PATH=/Users/kima/Documents/refilc/app/naplo/filcnaplo
COCOAPODS_PARALLEL_CODE_SIGN=true
FLUTTER_TARGET=lib/main.dart
FLUTTER_BUILD_DIR=build
FLUTTER_BUILD_NAME=4.2.2
FLUTTER_BUILD_NUMBER=222
EXCLUDED_ARCHS[sdk=iphonesimulator*]=i386
EXCLUDED_ARCHS[sdk=iphoneos*]=armv7
DART_OBFUSCATION=false
TRACK_WIDGET_CREATION=true
TREE_SHAKE_ICONS=false
PACKAGE_CONFIG=.dart_tool/package_config.json

View File

@ -0,0 +1,13 @@
#!/bin/sh
# This is a generated file; do not edit or check into version control.
export "FLUTTER_ROOT=/Users/kima/src/flutter"
export "FLUTTER_APPLICATION_PATH=/Users/kima/Documents/refilc/app/naplo/filcnaplo"
export "COCOAPODS_PARALLEL_CODE_SIGN=true"
export "FLUTTER_TARGET=lib/main.dart"
export "FLUTTER_BUILD_DIR=build"
export "FLUTTER_BUILD_NAME=4.2.2"
export "FLUTTER_BUILD_NUMBER=222"
export "DART_OBFUSCATION=false"
export "TRACK_WIDGET_CREATION=true"
export "TREE_SHAKE_ICONS=false"
export "PACKAGE_CONFIG=.dart_tool/package_config.json"

View File

@ -1,3 +1,4 @@
import 'dart:async';
import 'dart:convert';
import 'dart:developer';
@ -35,6 +36,9 @@ class FilcAPI {
// Share API
static const themeShare = "$baseUrl/v2/shared/theme/add";
static const themeGet = "$baseUrl/v2/shared/theme/get";
static const allThemes = "$themeGet/all";
static const themeByID = "$themeGet/";
static Future<bool> checkConnectivity() async =>
(await Connectivity().checkConnectivity()) != ConnectivityResult.none;
@ -194,15 +198,41 @@ class FilcAPI {
// sharing
static Future<void> addSharedTheme(SharedTheme theme) async {
try {
http.Response res =
await http.post(Uri.parse(themeShare), body: theme.json);
theme.json.remove('json');
theme.json['is_public'] = theme.isPublic.toString();
theme.json['background_color'] = theme.backgroundColor.value.toString();
theme.json['panels_color'] = theme.panelsColor.value.toString();
theme.json['accent_color'] = theme.accentColor.value.toString();
if (res.statusCode != 200) {
http.Response res = await http.post(
Uri.parse(themeShare),
body: theme.json,
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
);
if (res.statusCode != 201) {
throw "HTTP ${res.statusCode}: ${res.body}";
}
log('Shared theme successfully with ID: ${theme.id}');
} on Exception catch (error, stacktrace) {
log("ERROR: FilcAPI.addSharedTheme: $error $stacktrace");
}
}
static Future<Map?> getSharedTheme(String id) async {
try {
http.Response res = await http.get(Uri.parse(themeByID + id));
if (res.statusCode == 200) {
return (jsonDecode(res.body) as Map);
} else {
throw "HTTP ${res.statusCode}: ${res.body}";
}
} on Exception catch (error, stacktrace) {
log("ERROR: FilcAPI.addSharedTheme: $error $stacktrace");
}
return null;
}
}

View File

@ -25,9 +25,9 @@ class SharedTheme {
id: json['public_id'],
isPublic: json['is_public'] ?? false,
nickname: json['nickname'] ?? 'Anonymous',
backgroundColor: json['background_color'],
panelsColor: json['panels_color'],
accentColor: json['accent_color'],
backgroundColor: Color(json['background_color']),
panelsColor: Color(json['panels_color']),
accentColor: Color(json['accent_color']),
);
}
}

View File

@ -4,7 +4,13 @@ import 'package:flutter_feather_icons/flutter_feather_icons.dart';
enum LoginInputStyle { username, password, school }
class LoginInput extends StatefulWidget {
const LoginInput({Key? key, required this.style, this.controller, this.focusNode, this.onClear}) : super(key: key);
const LoginInput(
{Key? key,
required this.style,
this.controller,
this.focusNode,
this.onClear})
: super(key: key);
final Function()? onClear;
final LoginInputStyle style;
@ -59,8 +65,10 @@ class _LoginInputState extends State<LoginInput> {
borderRadius: BorderRadius.circular(12.0),
borderSide: const BorderSide(width: 0, color: Colors.transparent),
),
suffixIconConstraints: const BoxConstraints(maxHeight: 42.0, maxWidth: 48.0),
suffixIcon: widget.style == LoginInputStyle.password || widget.style == LoginInputStyle.school
suffixIconConstraints:
const BoxConstraints(maxHeight: 42.0, maxWidth: 48.0),
suffixIcon: widget.style == LoginInputStyle.password ||
widget.style == LoginInputStyle.school
? ClipOval(
child: Material(
type: MaterialType.transparency,

View File

@ -46,6 +46,7 @@ dependencies:
rounded_expansion_tile:
git:
url: https://github.com/kimaah/rounded_expansion_tile.git
go_router: ^10.1.2
dev_dependencies:
flutter_lints: ^1.0.0

View File

@ -19,7 +19,8 @@ class ShareProvider extends ChangeNotifier {
// }
Future<SharedTheme> shareCurrentTheme(BuildContext context,
{bool isPublic = false, bool shareNick = true}) async {
final SettingsProvider settings = Provider.of<SettingsProvider>(context);
final SettingsProvider settings =
Provider.of<SettingsProvider>(context, listen: false);
Map themeJson = {
'public_id': const Uuid().v4(),
@ -41,4 +42,16 @@ class ShareProvider extends ChangeNotifier {
return theme;
}
Future<SharedTheme?> getThemeById(BuildContext context,
{required String id}) async {
Map? themeJson = await FilcAPI.getSharedTheme(id);
if (themeJson != null) {
SharedTheme theme = SharedTheme.fromJson(themeJson);
return theme;
}
return null;
}
}

View File

@ -9,6 +9,9 @@
library hsv_picker;
import 'package:filcnaplo/models/shared_theme.dart';
import 'package:filcnaplo_mobile_ui/common/custom_snack_bar.dart';
import 'package:filcnaplo_premium/providers/share_provider.dart';
import 'package:filcnaplo_premium/ui/mobile/flutter_colorpicker/block_picker.dart';
import 'package:filcnaplo_premium/ui/mobile/flutter_colorpicker/palette.dart';
import 'package:filcnaplo_premium/ui/mobile/flutter_colorpicker/utils.dart';
@ -17,6 +20,7 @@ import 'package:filcnaplo_premium/ui/mobile/settings/theme.i18n.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:filcnaplo/theme/colors/colors.dart';
import 'package:provider/provider.dart';
class FilcColorPicker extends StatefulWidget {
const FilcColorPicker({
@ -48,6 +52,7 @@ class FilcColorPicker extends StatefulWidget {
this.hexInputController,
this.colorHistory,
this.onHistoryChanged,
required this.onThemeIdProvided,
}) : super(key: key);
final CustomColorMode colorMode;
@ -70,12 +75,17 @@ class FilcColorPicker extends StatefulWidget {
final TextEditingController? hexInputController;
final List<Color>? colorHistory;
final ValueChanged<List<Color>>? onHistoryChanged;
final void Function(SharedTheme theme) onThemeIdProvided;
@override
_FilcColorPickerState createState() => _FilcColorPickerState();
}
class _FilcColorPickerState extends State<FilcColorPicker> {
final idController = TextEditingController();
late final ShareProvider shareProvider;
HSVColor currentHsvColor = const HSVColor.fromAHSV(0.0, 0.0, 0.0, 0.0);
List<Color> colorHistory = [];
bool isAdvancedView = false;
@ -98,6 +108,7 @@ class _FilcColorPickerState extends State<FilcColorPicker> {
if (widget.colorHistory != null && widget.onHistoryChanged != null) {
colorHistory = widget.colorHistory ?? [];
}
shareProvider = Provider.of<ShareProvider>(context, listen: false);
super.initState();
}
@ -182,7 +193,8 @@ class _FilcColorPickerState extends State<FilcColorPicker> {
widget.portraitOnly) {
return Column(
children: [
if (widget.colorMode != CustomColorMode.theme)
if (widget.colorMode != CustomColorMode.theme &&
widget.colorMode != CustomColorMode.enterId)
Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Column(
@ -215,7 +227,9 @@ class _FilcColorPickerState extends State<FilcColorPicker> {
],
),
),
if (isAdvancedView && widget.colorMode != CustomColorMode.theme)
if (isAdvancedView &&
widget.colorMode != CustomColorMode.theme &&
widget.colorMode != CustomColorMode.enterId)
Padding(
padding: const EdgeInsets.only(bottom: 6.0),
child: ColorPickerInput(
@ -231,6 +245,53 @@ class _FilcColorPickerState extends State<FilcColorPicker> {
embeddedText: false,
),
),
if (widget.colorMode == CustomColorMode.enterId)
Padding(
padding:
const EdgeInsets.symmetric(vertical: 10.0, horizontal: 10.0),
child: Column(
children: [
TextField(
autocorrect: false,
autofocus: true,
onEditingComplete: () async {
SharedTheme? theme = await shareProvider.getThemeById(
context,
id: idController.text.replaceAll(' ', ''),
);
if (theme != null) {
widget.onThemeIdProvided(theme);
} else {
ScaffoldMessenger.of(context).showSnackBar(
CustomSnackBar(
content: Text("theme_not_found".i18n,
style: const TextStyle(color: Colors.white)),
backgroundColor: AppColors.of(context).red,
context: context,
),
);
}
},
controller: idController,
decoration: InputDecoration(
hintText: 'theme_id'.i18n,
),
),
// MaterialActionButton(
// child: Row(
// mainAxisSize: MainAxisSize.min,
// children: [
// Text('check_id'.i18n),
// ],
// ),
// backgroundColor: AppColors.of(context).filc,
// onPressed: () {},
// ),
],
),
),
if (widget.colorMode != CustomColorMode.enterId)
SizedBox(
height: 70 * (widget.colorMode == CustomColorMode.theme ? 2 : 1),
child: BlockPicker(
@ -281,7 +342,8 @@ class _FilcColorPickerState extends State<FilcColorPicker> {
onColorChanged: (c) => {},
),
),
if (widget.colorMode != CustomColorMode.theme)
if (widget.colorMode != CustomColorMode.theme &&
widget.colorMode != CustomColorMode.enterId)
Material(
color: Colors.transparent,
child: InkWell(

View File

@ -22,6 +22,7 @@ import 'package:flutter/services.dart';
import 'package:flutter_feather_icons/flutter_feather_icons.dart';
import 'package:provider/provider.dart';
import 'theme.i18n.dart';
import 'package:share_plus/share_plus.dart';
class PremiumCustomAccentColorSetting extends StatefulWidget {
const PremiumCustomAccentColorSetting({Key? key}) : super(key: key);
@ -31,7 +32,14 @@ class PremiumCustomAccentColorSetting extends StatefulWidget {
_PremiumCustomAccentColorSettingState();
}
enum CustomColorMode { theme, saved, accent, background, highlight }
enum CustomColorMode {
theme,
saved,
accent,
background,
highlight,
enterId,
}
class _PremiumCustomAccentColorSettingState
extends State<PremiumCustomAccentColorSetting>
@ -99,7 +107,7 @@ class _PremiumCustomAccentColorSettingState
@override
void initState() {
super.initState();
_colorsTabController = TabController(length: 4, vsync: this);
_colorsTabController = TabController(length: 5, vsync: this);
_testTabController = TabController(length: 4, vsync: this);
settings = Provider.of<SettingsProvider>(context, listen: false);
shareProvider = Provider.of<ShareProvider>(context, listen: false);
@ -137,10 +145,14 @@ class _PremiumCustomAccentColorSettingState
return settings.customHighlightColor;
case CustomColorMode.accent:
return settings.customAccentColor;
case CustomColorMode.enterId:
// do nothing here lol
break;
}
}
void updateCustomColor(dynamic v, bool store) {
void updateCustomColor(dynamic v, bool store,
{Color? accent, Color? background, Color? panels}) {
if (colorMode != CustomColorMode.theme) {
settings.update(accentColor: AccentColor.custom, store: store);
}
@ -173,6 +185,11 @@ class _PremiumCustomAccentColorSettingState
case CustomColorMode.accent:
settings.update(customAccentColor: v, store: store);
break;
case CustomColorMode.enterId:
settings.update(customBackgroundColor: background, store: store);
settings.update(customHighlightColor: panels, store: store);
settings.update(customAccentColor: accent, store: store);
break;
}
}
@ -253,7 +270,8 @@ class _PremiumCustomAccentColorSettingState
// );
SharedTheme theme =
await shareProvider.shareCurrentTheme(context);
print(theme.id);
Share.share(theme.id,
subject: 'reFilc Téma / reFilc Theme');
},
icon: const Icon(
FeatherIcons.share2,
@ -620,6 +638,9 @@ class _PremiumCustomAccentColorSettingState
tab: Tab(
text: "colorpicker_presets"
.i18n)),
ColorTab(
color: unknownColor,
tab: Tab(text: "enter_id".i18n)),
/*ColorTab(
color:
settings.customAccentColor ??
@ -671,25 +692,31 @@ class _PremiumCustomAccentColorSettingState
CustomColorMode.theme;
});
break;
case 1:
setState(() {
colorMode =
CustomColorMode.enterId;
});
break;
/*case 1:
setState(() {
colorMode =
CustomColorMode.saved;
});
break;*/
case 1:
case 2:
setState(() {
colorMode =
CustomColorMode.background;
});
break;
case 2:
case 3:
setState(() {
colorMode =
CustomColorMode.highlight;
});
break;
case 3:
case 4:
setState(() {
colorMode =
CustomColorMode.accent;
@ -753,6 +780,19 @@ class _PremiumCustomAccentColorSettingState
});
setTheme(settings.theme, true);
},
onThemeIdProvided: (theme) {
setState(() {
updateCustomColor(
null,
true,
accent: theme.accentColor,
background:
theme.backgroundColor,
panels: theme.panelsColor,
);
});
setTheme(settings.theme, true);
},
),
),
),

View File

@ -11,6 +11,9 @@ extension SettingsLocalization on String {
"colorpicker_accent": "Accent",
"need_sub": "You need Kupak subscription to use modify this.",
"advanced": "Advanced",
"enter_id": "Enter ID",
"theme_id": "Theme ID...",
"theme_not_found": "Theme not found!",
},
"hu_hu": {
"theme_prev": "Előnézet",
@ -20,6 +23,9 @@ extension SettingsLocalization on String {
"colorpicker_accent": "Színtónus",
"need_sub": "A módosításhoz Kupak szintű támogatás szükséges.",
"advanced": "Haladó",
"enter_id": "ID megadása",
"theme_id": "Téma azonosító...",
"theme_not_found": "A téma nem található!",
},
"de_de": {
"theme_prev": "Vorschau",
@ -30,6 +36,9 @@ extension SettingsLocalization on String {
"need_sub":
"Sie benötigen ein Kupak-Abonnement, um diese Funktion zu ändern.",
"advanced": "Fortschrittlich",
"enter_id": "Geben Sie die ID ein",
"theme_id": "Themen-ID...",
"theme_not_found": "Thema nicht gefunden!",
},
};