commit
19691a1dc0
1
.gitignore
vendored
1
.gitignore
vendored
@ -49,3 +49,4 @@ key.properties
|
||||
|
||||
.flutter-plugins*
|
||||
filcnaplo/ios/Flutter/flutter_export_environment 4.sh
|
||||
filcnaplo/ios/Flutter/Generated 4.xcconfig
|
||||
|
@ -1,14 +0,0 @@
|
||||
// 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.0
|
||||
FLUTTER_BUILD_NUMBER=220
|
||||
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
|
@ -1,14 +0,0 @@
|
||||
// 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.0
|
||||
FLUTTER_BUILD_NUMBER=220
|
||||
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
|
@ -1,13 +0,0 @@
|
||||
#!/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.0"
|
||||
export "FLUTTER_BUILD_NUMBER=220"
|
||||
export "DART_OBFUSCATION=false"
|
||||
export "TRACK_WIDGET_CREATION=true"
|
||||
export "TREE_SHAKE_ICONS=false"
|
||||
export "PACKAGE_CONFIG=.dart_tool/package_config.json"
|
@ -1,13 +0,0 @@
|
||||
#!/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.0"
|
||||
export "FLUTTER_BUILD_NUMBER=220"
|
||||
export "DART_OBFUSCATION=false"
|
||||
export "TRACK_WIDGET_CREATION=true"
|
||||
export "TREE_SHAKE_ICONS=false"
|
||||
export "PACKAGE_CONFIG=.dart_tool/package_config.json"
|
@ -1,3 +1,4 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:developer';
|
||||
|
||||
@ -6,6 +7,7 @@ import 'package:filcnaplo/models/config.dart';
|
||||
import 'package:filcnaplo/models/news.dart';
|
||||
import 'package:filcnaplo/models/release.dart';
|
||||
import 'package:filcnaplo/models/settings.dart';
|
||||
import 'package:filcnaplo/models/shared_theme.dart';
|
||||
import 'package:filcnaplo/models/supporter.dart';
|
||||
import 'package:filcnaplo_kreta_api/models/school.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
@ -13,15 +15,18 @@ import 'package:http/http.dart' as http;
|
||||
import 'package:connectivity_plus/connectivity_plus.dart';
|
||||
|
||||
class FilcAPI {
|
||||
// API base
|
||||
static const baseUrl = "https://api.refilc.hu";
|
||||
|
||||
// Public API
|
||||
static const schoolList = "https://api.refilc.hu/v1/public/school-list";
|
||||
static const news = "https://api.refilc.hu/v1/public/news";
|
||||
static const supporters = "https://api.refilc.hu/v1/public/supporters";
|
||||
static const schoolList = "$baseUrl/v1/public/school-list";
|
||||
static const news = "$baseUrl/v1/public/news";
|
||||
static const supporters = "$baseUrl/v1/public/supporters";
|
||||
|
||||
// Private API
|
||||
static const ads = "https://api.refilc.hu/v1/private/ads";
|
||||
static const config = "https://api.refilc.hu/v1/private/config";
|
||||
static const reportApi = "https://api.refilc.hu/v1/private/crash-report";
|
||||
static const ads = "$baseUrl/v1/private/ads";
|
||||
static const config = "$baseUrl/v1/private/config";
|
||||
static const reportApi = "$baseUrl/v1/private/crash-report";
|
||||
static const premiumApi = "https://api.filcnaplo.hu/premium/activate";
|
||||
// static const premiumScopesApi = "https://api.filcnaplo.hu/premium/scopes";
|
||||
|
||||
@ -29,6 +34,12 @@ class FilcAPI {
|
||||
static const repo = "refilc/naplo";
|
||||
static const releases = "https://api.github.com/repos/$repo/releases";
|
||||
|
||||
// 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;
|
||||
|
||||
@ -183,6 +194,46 @@ class FilcAPI {
|
||||
log("ERROR: FilcAPI.sendReport: $error $stacktrace");
|
||||
}
|
||||
}
|
||||
|
||||
// sharing
|
||||
static Future<void> addSharedTheme(SharedTheme theme) async {
|
||||
try {
|
||||
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();
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
class ErrorReport {
|
||||
|
@ -14,6 +14,7 @@ import 'package:filcnaplo/theme/theme.dart';
|
||||
import 'package:filcnaplo_kreta_api/client/client.dart';
|
||||
import 'package:filcnaplo_kreta_api/providers/grade_provider.dart';
|
||||
import 'package:filcnaplo_premium/providers/goal_provider.dart';
|
||||
import 'package:filcnaplo_premium/providers/share_provider.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@ -99,49 +100,78 @@ class App extends StatelessWidget {
|
||||
Provider<KretaClient>(create: (_) => kreta),
|
||||
Provider<DatabaseProvider>(create: (context) => database),
|
||||
ChangeNotifierProvider<ThemeModeObserver>(
|
||||
create: (context) =>
|
||||
ThemeModeObserver(initialTheme: settings.theme)),
|
||||
create: (context) => ThemeModeObserver(
|
||||
initialTheme: settings.theme,
|
||||
),
|
||||
),
|
||||
ChangeNotifierProvider<NewsProvider>(
|
||||
create: (context) => NewsProvider(context: context)),
|
||||
create: (context) => NewsProvider(context: context),
|
||||
),
|
||||
ChangeNotifierProvider<UpdateProvider>(
|
||||
create: (context) => UpdateProvider(context: context)),
|
||||
create: (context) => UpdateProvider(context: context),
|
||||
),
|
||||
ChangeNotifierProvider<AdProvider>(
|
||||
create: (context) => AdProvider(context: context)),
|
||||
create: (context) => AdProvider(context: context),
|
||||
),
|
||||
|
||||
// user data (kreten) providers
|
||||
ChangeNotifierProvider<GradeProvider>(
|
||||
create: (_) => GradeProvider(
|
||||
settings: settings,
|
||||
user: user,
|
||||
database: database,
|
||||
kreta: kreta)),
|
||||
create: (_) => GradeProvider(
|
||||
settings: settings,
|
||||
user: user,
|
||||
database: database,
|
||||
kreta: kreta,
|
||||
),
|
||||
),
|
||||
ChangeNotifierProvider<TimetableProvider>(create: (_) => timetable),
|
||||
ChangeNotifierProvider<ExamProvider>(
|
||||
create: (context) => ExamProvider(context: context)),
|
||||
create: (context) => ExamProvider(context: context),
|
||||
),
|
||||
ChangeNotifierProvider<HomeworkProvider>(
|
||||
create: (context) =>
|
||||
HomeworkProvider(context: context, database: database)),
|
||||
create: (context) => HomeworkProvider(
|
||||
context: context,
|
||||
database: database,
|
||||
),
|
||||
),
|
||||
ChangeNotifierProvider<MessageProvider>(
|
||||
create: (context) => MessageProvider(context: context)),
|
||||
create: (context) => MessageProvider(context: context),
|
||||
),
|
||||
ChangeNotifierProvider<NoteProvider>(
|
||||
create: (context) => NoteProvider(context: context)),
|
||||
create: (context) => NoteProvider(context: context),
|
||||
),
|
||||
ChangeNotifierProvider<EventProvider>(
|
||||
create: (context) => EventProvider(context: context)),
|
||||
create: (context) => EventProvider(context: context),
|
||||
),
|
||||
ChangeNotifierProvider<AbsenceProvider>(
|
||||
create: (context) => AbsenceProvider(context: context)),
|
||||
create: (context) => AbsenceProvider(context: context),
|
||||
),
|
||||
|
||||
// other providers
|
||||
ChangeNotifierProvider<GradeCalculatorProvider>(
|
||||
create: (_) => GradeCalculatorProvider(
|
||||
settings: settings,
|
||||
user: user,
|
||||
database: database,
|
||||
kreta: kreta)),
|
||||
create: (_) => GradeCalculatorProvider(
|
||||
settings: settings,
|
||||
user: user,
|
||||
database: database,
|
||||
kreta: kreta,
|
||||
),
|
||||
),
|
||||
ChangeNotifierProvider<LiveCardProvider>(
|
||||
create: (context) =>
|
||||
LiveCardProvider(timetable: timetable, settings: settings)),
|
||||
create: (context) => LiveCardProvider(
|
||||
timetable: timetable,
|
||||
settings: settings,
|
||||
),
|
||||
),
|
||||
ChangeNotifierProvider<GoalProvider>(
|
||||
create: (context) => GoalProvider(database: database, user: user)),
|
||||
create: (context) => GoalProvider(
|
||||
database: database,
|
||||
user: user,
|
||||
),
|
||||
),
|
||||
ChangeNotifierProvider<ShareProvider>(
|
||||
create: (context) => ShareProvider(
|
||||
user: user,
|
||||
),
|
||||
),
|
||||
],
|
||||
child: Consumer<ThemeModeObserver>(
|
||||
builder: (context, themeMode, child) {
|
||||
|
@ -3,18 +3,22 @@ import 'dart:io';
|
||||
class Config {
|
||||
String _userAgent;
|
||||
Map? json;
|
||||
static const String _version = String.fromEnvironment("APPVER", defaultValue: "2.2.0");
|
||||
static const String _version =
|
||||
String.fromEnvironment("APPVER", defaultValue: "3.0.4");
|
||||
|
||||
Config({required String userAgent, this.json}) : _userAgent = userAgent;
|
||||
|
||||
factory Config.fromJson(Map json) {
|
||||
return Config(
|
||||
userAgent: json["user_agent"] ?? "hu.refilc.naplo/\$0/\$1/\$2",
|
||||
userAgent: json["user_agent"] ?? "hu.ekreta.student/\$0/\$1/\$2",
|
||||
json: json,
|
||||
);
|
||||
}
|
||||
|
||||
String get userAgent => _userAgent.replaceAll("\$0", _version).replaceAll("\$1", platform).replaceAll("\$2", "0");
|
||||
String get userAgent => _userAgent
|
||||
.replaceAll("\$0", _version)
|
||||
.replaceAll("\$1", platform)
|
||||
.replaceAll("\$2", "0");
|
||||
|
||||
static String get platform {
|
||||
if (Platform.isAndroid) {
|
||||
|
@ -313,7 +313,7 @@ class SettingsProvider extends ChangeNotifier {
|
||||
bellDelay: 0,
|
||||
gradeOpeningFun: true,
|
||||
iconPack: IconPack.cupertino,
|
||||
customAccentColor: const Color(0xff20AC9B),
|
||||
customAccentColor: const Color(0xff3D7BF4),
|
||||
customBackgroundColor: const Color(0xff000000),
|
||||
customHighlightColor: const Color(0xff222222),
|
||||
premiumScopes: [PremiumScopes.all],
|
||||
|
33
filcnaplo/lib/models/shared_theme.dart
Normal file
33
filcnaplo/lib/models/shared_theme.dart
Normal file
@ -0,0 +1,33 @@
|
||||
import 'dart:ui';
|
||||
|
||||
class SharedTheme {
|
||||
Map json;
|
||||
String id;
|
||||
bool isPublic;
|
||||
String nickname;
|
||||
Color backgroundColor;
|
||||
Color panelsColor;
|
||||
Color accentColor;
|
||||
|
||||
SharedTheme({
|
||||
required this.json,
|
||||
required this.id,
|
||||
this.isPublic = false,
|
||||
this.nickname = 'Anonymous',
|
||||
required this.backgroundColor,
|
||||
required this.panelsColor,
|
||||
required this.accentColor,
|
||||
});
|
||||
|
||||
factory SharedTheme.fromJson(Map json) {
|
||||
return SharedTheme(
|
||||
json: json,
|
||||
id: json['public_id'],
|
||||
isPublic: json['is_public'] ?? false,
|
||||
nickname: json['nickname'] ?? 'Anonymous',
|
||||
backgroundColor: Color(json['background_color']),
|
||||
panelsColor: Color(json['panels_color']),
|
||||
accentColor: Color(json['accent_color']),
|
||||
);
|
||||
}
|
||||
}
|
@ -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,
|
||||
|
@ -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
|
||||
|
58
filcnaplo_premium/lib/providers/share_provider.dart
Normal file
58
filcnaplo_premium/lib/providers/share_provider.dart
Normal file
@ -0,0 +1,58 @@
|
||||
import 'package:filcnaplo/api/client.dart';
|
||||
import 'package:filcnaplo/api/providers/user_provider.dart';
|
||||
import 'package:filcnaplo/models/settings.dart';
|
||||
import 'package:filcnaplo/models/shared_theme.dart';
|
||||
// import 'package:filcnaplo/models/shared_theme.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:uuid/uuid.dart';
|
||||
|
||||
class ShareProvider extends ChangeNotifier {
|
||||
final UserProvider _user;
|
||||
|
||||
ShareProvider({
|
||||
required UserProvider user,
|
||||
}) : _user = user;
|
||||
|
||||
// Future<void> shareTheme({required SharedTheme theme}) async {
|
||||
|
||||
// }
|
||||
Future<SharedTheme> shareCurrentTheme(BuildContext context,
|
||||
{bool isPublic = false, bool shareNick = true}) async {
|
||||
final SettingsProvider settings =
|
||||
Provider.of<SettingsProvider>(context, listen: false);
|
||||
|
||||
Map themeJson = {
|
||||
'public_id': const Uuid().v4(),
|
||||
'is_public': isPublic,
|
||||
'nickname': shareNick ? _user.nickname : 'Anonymous',
|
||||
'background_color': (settings.customBackgroundColor ??
|
||||
SettingsProvider.defaultSettings().customBackgroundColor)
|
||||
?.value,
|
||||
'panels_color': (settings.customHighlightColor ??
|
||||
SettingsProvider.defaultSettings().customHighlightColor)
|
||||
?.value,
|
||||
'accent_color': (settings.customAccentColor ??
|
||||
SettingsProvider.defaultSettings().customAccentColor)
|
||||
?.value ??
|
||||
const Color(0xFF3D7BF4).value,
|
||||
};
|
||||
|
||||
SharedTheme theme = SharedTheme.fromJson(themeJson);
|
||||
FilcAPI.addSharedTheme(theme);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
@ -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,57 +245,105 @@ class _FilcColorPickerState extends State<FilcColorPicker> {
|
||||
embeddedText: false,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 70 * (widget.colorMode == CustomColorMode.theme ? 2 : 1),
|
||||
child: BlockPicker(
|
||||
pickerColor: Colors.red,
|
||||
layoutBuilder: (context, colors, child) {
|
||||
return GridView.count(
|
||||
shrinkWrap: true,
|
||||
crossAxisCount:
|
||||
widget.colorMode == CustomColorMode.theme ? 2 : 1,
|
||||
scrollDirection: Axis.horizontal,
|
||||
crossAxisSpacing: 15,
|
||||
physics: const BouncingScrollPhysics(),
|
||||
mainAxisSpacing: 15,
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 12.0, vertical: 8.0),
|
||||
children: List.generate(
|
||||
colors.toSet().length +
|
||||
(widget.colorMode == CustomColorMode.theme ? 1 : 0),
|
||||
(index) {
|
||||
if (widget.colorMode == CustomColorMode.theme) {
|
||||
if (index == 0) {
|
||||
return GestureDetector(
|
||||
onTap: () => widget.onColorChangeEnd(
|
||||
Colors.transparent,
|
||||
adaptive: true),
|
||||
child: ColorIndicator(
|
||||
HSVColor.fromColor(
|
||||
const Color.fromARGB(255, 255, 238, 177)),
|
||||
icon: CupertinoIcons.wand_stars,
|
||||
currentHsvColor: currentHsvColor,
|
||||
width: 30,
|
||||
height: 30,
|
||||
adaptive: true),
|
||||
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,
|
||||
),
|
||||
);
|
||||
}
|
||||
index--;
|
||||
}
|
||||
return GestureDetector(
|
||||
onTap: () => widget.onColorChangeEnd(colors[index]),
|
||||
child: ColorIndicator(HSVColor.fromColor(colors[index]),
|
||||
currentHsvColor: currentHsvColor,
|
||||
width: 30,
|
||||
height: 30),
|
||||
);
|
||||
}),
|
||||
);
|
||||
},
|
||||
onColorChanged: (c) => {},
|
||||
},
|
||||
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.theme)
|
||||
if (widget.colorMode != CustomColorMode.enterId)
|
||||
SizedBox(
|
||||
height: 70 * (widget.colorMode == CustomColorMode.theme ? 2 : 1),
|
||||
child: BlockPicker(
|
||||
pickerColor: Colors.red,
|
||||
layoutBuilder: (context, colors, child) {
|
||||
return GridView.count(
|
||||
shrinkWrap: true,
|
||||
crossAxisCount:
|
||||
widget.colorMode == CustomColorMode.theme ? 2 : 1,
|
||||
scrollDirection: Axis.horizontal,
|
||||
crossAxisSpacing: 15,
|
||||
physics: const BouncingScrollPhysics(),
|
||||
mainAxisSpacing: 15,
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 12.0, vertical: 8.0),
|
||||
children: List.generate(
|
||||
colors.toSet().length +
|
||||
(widget.colorMode == CustomColorMode.theme ? 1 : 0),
|
||||
(index) {
|
||||
if (widget.colorMode == CustomColorMode.theme) {
|
||||
if (index == 0) {
|
||||
return GestureDetector(
|
||||
onTap: () => widget.onColorChangeEnd(
|
||||
Colors.transparent,
|
||||
adaptive: true),
|
||||
child: ColorIndicator(
|
||||
HSVColor.fromColor(
|
||||
const Color.fromARGB(255, 255, 238, 177)),
|
||||
icon: CupertinoIcons.wand_stars,
|
||||
currentHsvColor: currentHsvColor,
|
||||
width: 30,
|
||||
height: 30,
|
||||
adaptive: true),
|
||||
);
|
||||
}
|
||||
index--;
|
||||
}
|
||||
return GestureDetector(
|
||||
onTap: () => widget.onColorChangeEnd(colors[index]),
|
||||
child: ColorIndicator(HSVColor.fromColor(colors[index]),
|
||||
currentHsvColor: currentHsvColor,
|
||||
width: 30,
|
||||
height: 30),
|
||||
);
|
||||
}),
|
||||
);
|
||||
},
|
||||
onColorChanged: (c) => {},
|
||||
),
|
||||
),
|
||||
if (widget.colorMode != CustomColorMode.theme &&
|
||||
widget.colorMode != CustomColorMode.enterId)
|
||||
Material(
|
||||
color: Colors.transparent,
|
||||
child: InkWell(
|
||||
|
26
filcnaplo_premium/lib/ui/mobile/settings/share_theme.dart
Normal file
26
filcnaplo_premium/lib/ui/mobile/settings/share_theme.dart
Normal file
@ -0,0 +1,26 @@
|
||||
import 'package:filcnaplo/models/settings.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class PremiumShareTheme extends StatefulWidget {
|
||||
const PremiumShareTheme({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<PremiumShareTheme> createState() => _PremiumShareThemeState();
|
||||
}
|
||||
|
||||
class _PremiumShareThemeState extends State<PremiumShareTheme>
|
||||
with TickerProviderStateMixin {
|
||||
late final SettingsProvider settingsProvider;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
settingsProvider = Provider.of<SettingsProvider>(context, listen: false);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return const Scaffold();
|
||||
}
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
import 'package:filcnaplo/models/settings.dart';
|
||||
import 'package:filcnaplo/models/shared_theme.dart';
|
||||
import 'package:filcnaplo/theme/colors/accent.dart';
|
||||
import 'package:filcnaplo/theme/colors/colors.dart';
|
||||
import 'package:filcnaplo/theme/observer.dart';
|
||||
@ -13,12 +14,15 @@ import 'package:filcnaplo_mobile_ui/common/widgets/grade/new_grades.dart';
|
||||
import 'package:filcnaplo_mobile_ui/common/widgets/homework/homework_tile.dart';
|
||||
import 'package:filcnaplo_premium/models/premium_scopes.dart';
|
||||
import 'package:filcnaplo_premium/providers/premium_provider.dart';
|
||||
import 'package:filcnaplo_premium/providers/share_provider.dart';
|
||||
import 'package:filcnaplo_premium/ui/mobile/flutter_colorpicker/colorpicker.dart';
|
||||
import 'package:filcnaplo_premium/ui/mobile/premium/upsell.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
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);
|
||||
@ -28,12 +32,20 @@ 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>
|
||||
with TickerProviderStateMixin {
|
||||
late final SettingsProvider settings;
|
||||
late final ShareProvider shareProvider;
|
||||
bool colorSelection = false;
|
||||
bool customColorMenu = false;
|
||||
CustomColorMode colorMode = CustomColorMode.theme;
|
||||
@ -95,9 +107,10 @@ 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);
|
||||
|
||||
_openAnimController = AnimationController(
|
||||
vsync: this, duration: const Duration(milliseconds: 750));
|
||||
@ -132,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);
|
||||
}
|
||||
@ -168,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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -230,6 +252,34 @@ class _PremiumCustomAccentColorSettingState
|
||||
appBar: AppBar(
|
||||
surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
|
||||
leading: BackButton(color: AppColors.of(context).text),
|
||||
actions: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 10.0),
|
||||
child: IconButton(
|
||||
focusColor: Colors.transparent,
|
||||
highlightColor: Colors.transparent,
|
||||
splashColor: Colors.transparent,
|
||||
onPressed: () async {
|
||||
// ScaffoldMessenger.of(context).showSnackBar(
|
||||
// const SnackBar(
|
||||
// duration: Duration(milliseconds: 1000),
|
||||
// content: Text(
|
||||
// "Hamarosan...",
|
||||
// ),
|
||||
// ),
|
||||
// );
|
||||
SharedTheme theme =
|
||||
await shareProvider.shareCurrentTheme(context);
|
||||
Share.share(theme.id,
|
||||
subject: 'reFilc Téma / reFilc Theme');
|
||||
},
|
||||
icon: const Icon(
|
||||
FeatherIcons.share2,
|
||||
size: 22.0,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
title: Text(
|
||||
"theme_prev".i18n,
|
||||
style: TextStyle(color: AppColors.of(context).text),
|
||||
@ -588,6 +638,9 @@ class _PremiumCustomAccentColorSettingState
|
||||
tab: Tab(
|
||||
text: "colorpicker_presets"
|
||||
.i18n)),
|
||||
ColorTab(
|
||||
color: unknownColor,
|
||||
tab: Tab(text: "enter_id".i18n)),
|
||||
/*ColorTab(
|
||||
color:
|
||||
settings.customAccentColor ??
|
||||
@ -639,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;
|
||||
@ -721,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);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -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!",
|
||||
},
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user