simplified news provider

This commit is contained in:
Kima 2023-08-26 19:12:03 +02:00
parent 6d4939d88a
commit bc1ec45855
6 changed files with 111 additions and 52 deletions

View File

@ -1,7 +1,4 @@
// ignore_for_file: use_build_context_synchronously // ignore_for_file: use_build_context_synchronously
import 'dart:math';
import 'package:filcnaplo/api/client.dart'; import 'package:filcnaplo/api/client.dart';
import 'package:filcnaplo/models/news.dart'; import 'package:filcnaplo/models/news.dart';
import 'package:filcnaplo/models/settings.dart'; import 'package:filcnaplo/models/settings.dart';
@ -11,7 +8,7 @@ import 'package:provider/provider.dart';
class NewsProvider extends ChangeNotifier { class NewsProvider extends ChangeNotifier {
// Private // Private
late List<News> _news; late List<News> _news;
late int _state; //late int _state;
late int _fresh; late int _fresh;
bool show = false; bool show = false;
late BuildContext _context; late BuildContext _context;
@ -30,56 +27,83 @@ class NewsProvider extends ChangeNotifier {
Future<void> restore() async { Future<void> restore() async {
// Load news state from the database // Load news state from the database
var state_ = Provider.of<SettingsProvider>(_context, listen: false).newsState; var seen_ = Provider.of<SettingsProvider>(_context, listen: false).seenNews;
if (state_ == -1) { if (seen_.isEmpty) {
var news_ = await FilcAPI.getNews(); var news_ = await FilcAPI.getNews();
if (news_ != null) { if (news_ != null) {
state_ = news_.length;
_news = news_; _news = news_;
show = true;
} }
} }
_state = state_; //_state = seen_;
Provider.of<SettingsProvider>(_context, listen: false).update(newsState: _state); // Provider.of<SettingsProvider>(_context, listen: false)
// .update(seenNewsId: news_.id);
} }
Future<void> fetch() async { Future<void> fetch() async {
var news_ = await FilcAPI.getNews(); var news_ = await FilcAPI.getNews();
if (news_ == null) return; if (news_ == null) return;
show = false;
_news = news_; _news = news_;
_fresh = news_.length - _state;
if (_fresh < 0) { for (var news in news_) {
_state = news_.length; if (news.expireDate.isAfter(DateTime.now()) &&
Provider.of<SettingsProvider>(_context, listen: false).update(newsState: _state); Provider.of<SettingsProvider>(_context, listen: false)
} .seenNews
.contains(news.id) ==
_fresh = max(_fresh, 0); false) {
if (_fresh > 0) {
show = true; show = true;
Provider.of<SettingsProvider>(_context, listen: false)
.update(seenNewsId: news.id);
notifyListeners(); notifyListeners();
} }
} }
// print(news_.length);
// print(_state);
// _news = news_;
// _fresh = news_.length - _state;
// if (_fresh < 0) {
// _state = news_.length;
// Provider.of<SettingsProvider>(_context, listen: false)
// .update(newsState: _state);
// }
// _fresh = max(_fresh, 0);
// if (_fresh > 0) {
// show = true;
// notifyListeners();
// }
// print(_fresh);
// print(_state);
// print(show);
}
void lock() => show = false; void lock() => show = false;
void release() { void release() {
if (_fresh == 0) return; // if (_fresh == 0) return;
_fresh--; // _fresh--;
_state++; // //_state++;
Provider.of<SettingsProvider>(_context, listen: false).update(newsState: _state); // // Provider.of<SettingsProvider>(_context, listen: false)
// // .update(seenNewsId: _state);
if (_fresh > 0) { // if (_fresh > 0) {
show = true; // show = true;
} else { // } else {
show = false; // show = false;
} // }
notifyListeners(); // notifyListeners();
} }
} }

View File

@ -12,7 +12,8 @@ import 'package:sqflite_common_ffi_web/sqflite_ffi_web.dart';
const settingsDB = DatabaseStruct("settings", { const settingsDB = DatabaseStruct("settings", {
"language": String, "start_page": int, "rounding": int, "theme": int, "language": String, "start_page": int, "rounding": int, "theme": int,
"accent_color": int, "news": int, "news_state": int, "developer_mode": int, "accent_color": int, "news": int, "seen_news": String,
"developer_mode": int,
"update_channel": int, "config": String, "custom_accent_color": int, "update_channel": int, "config": String, "custom_accent_color": int,
"custom_background_color": int, "custom_highlight_color": int, // general "custom_background_color": int, "custom_highlight_color": int, // general
"grade_color1": int, "grade_color2": int, "grade_color3": int, "grade_color1": int, "grade_color2": int, "grade_color3": int,
@ -92,6 +93,8 @@ Future<Database> initDB(DatabaseProvider database) async {
"group_averages": "[]", "group_averages": "[]",
// renamed subjects // non kreta data // renamed subjects // non kreta data
"renamed_subjects": "{}", "renamed_subjects": "{}",
// renamed teachers // non kreta data
"renamed_teachers": "{}",
// "subject_lesson_count": "{}", // non kreta data // "subject_lesson_count": "{}", // non kreta data
"last_seen_grade": 0, "last_seen_grade": 0,
}); });

View File

@ -1,30 +1,36 @@
class News { class News {
String id;
String title; String title;
String content; String content;
String link; String link;
String openLabel; String openLabel;
String platform; String platform;
bool emergency; bool emergency;
DateTime expireDate;
Map? json; Map? json;
News({ News({
required this.id,
required this.title, required this.title,
required this.content, required this.content,
required this.link, required this.link,
required this.openLabel, required this.openLabel,
required this.platform, required this.platform,
required this.emergency, required this.emergency,
required this.expireDate,
this.json, this.json,
}); });
factory News.fromJson(Map json) { factory News.fromJson(Map json) {
return News( return News(
id: json["id"] ?? "",
title: json["title"] ?? "", title: json["title"] ?? "",
content: json["content"] ?? "", content: json["content"] ?? "",
link: json["link"] ?? "", link: json["link"] ?? "",
openLabel: json["open_label"] ?? "", openLabel: json["open_label"] ?? "",
platform: json["platform"] ?? "", platform: json["platform"] ?? "",
emergency: json["emergency"] ?? false, emergency: json["emergency"] ?? false,
expireDate: DateTime.parse(json["expire_date"] ?? ''),
json: json, json: json,
); );
} }

View File

@ -29,7 +29,7 @@ class SettingsProvider extends ChangeNotifier {
// zero is one, ... // zero is one, ...
List<Color> _gradeColors; List<Color> _gradeColors;
bool _newsEnabled; bool _newsEnabled;
int _newsState; String _seenNews;
bool _notificationsEnabled; bool _notificationsEnabled;
/* /*
notificationsBitfield values: notificationsBitfield values:
@ -81,7 +81,7 @@ class SettingsProvider extends ChangeNotifier {
required AccentColor accentColor, required AccentColor accentColor,
required List<Color> gradeColors, required List<Color> gradeColors,
required bool newsEnabled, required bool newsEnabled,
required int newsState, required String seenNews,
required bool notificationsEnabled, required bool notificationsEnabled,
required int notificationsBitfield, required int notificationsBitfield,
required bool developerMode, required bool developerMode,
@ -118,7 +118,7 @@ class SettingsProvider extends ChangeNotifier {
_accentColor = accentColor, _accentColor = accentColor,
_gradeColors = gradeColors, _gradeColors = gradeColors,
_newsEnabled = newsEnabled, _newsEnabled = newsEnabled,
_newsState = newsState, _seenNews = seenNews,
_notificationsEnabled = notificationsEnabled, _notificationsEnabled = notificationsEnabled,
_notificationsBitfield = notificationsBitfield, _notificationsBitfield = notificationsBitfield,
_developerMode = developerMode, _developerMode = developerMode,
@ -158,6 +158,8 @@ class SettingsProvider extends ChangeNotifier {
log("[ERROR] SettingsProvider.fromMap: $e"); log("[ERROR] SettingsProvider.fromMap: $e");
} }
print(map['seen_news']);
return SettingsProvider( return SettingsProvider(
database: database, database: database,
language: map["language"], language: map["language"],
@ -173,7 +175,7 @@ class SettingsProvider extends ChangeNotifier {
Color(map["grade_color5"]), Color(map["grade_color5"]),
], ],
newsEnabled: map["news"] == 1, newsEnabled: map["news"] == 1,
newsState: map["news_state"], seenNews: map["seen_news"],
notificationsEnabled: map["notifications"] == 1, notificationsEnabled: map["notifications"] == 1,
notificationsBitfield: map["notifications_bitfield"], notificationsBitfield: map["notifications_bitfield"],
notificationPollInterval: map["notification_poll_interval"], notificationPollInterval: map["notification_poll_interval"],
@ -214,7 +216,7 @@ class SettingsProvider extends ChangeNotifier {
"theme": _theme.index, "theme": _theme.index,
"accent_color": _accentColor.index, "accent_color": _accentColor.index,
"news": _newsEnabled ? 1 : 0, "news": _newsEnabled ? 1 : 0,
"news_state": _newsState, "seen_news": _seenNews,
"notifications": _notificationsEnabled ? 1 : 0, "notifications": _notificationsEnabled ? 1 : 0,
"notifications_bitfield": _notificationsBitfield, "notifications_bitfield": _notificationsBitfield,
"developer_mode": _developerMode ? 1 : 0, "developer_mode": _developerMode ? 1 : 0,
@ -266,7 +268,7 @@ class SettingsProvider extends ChangeNotifier {
DarkMobileAppColors().gradeFive, DarkMobileAppColors().gradeFive,
], ],
newsEnabled: true, newsEnabled: true,
newsState: -1, seenNews: '',
notificationsEnabled: true, notificationsEnabled: true,
notificationsBitfield: 255, notificationsBitfield: 255,
developerMode: false, developerMode: false,
@ -306,7 +308,7 @@ class SettingsProvider extends ChangeNotifier {
AccentColor get accentColor => _accentColor; AccentColor get accentColor => _accentColor;
List<Color> get gradeColors => _gradeColors; List<Color> get gradeColors => _gradeColors;
bool get newsEnabled => _newsEnabled; bool get newsEnabled => _newsEnabled;
int get newsState => _newsState; List<String> get seenNews => _seenNews.split(',');
bool get notificationsEnabled => _notificationsEnabled; bool get notificationsEnabled => _notificationsEnabled;
int get notificationsBitfield => _notificationsBitfield; int get notificationsBitfield => _notificationsBitfield;
bool get developerMode => _developerMode; bool get developerMode => _developerMode;
@ -348,7 +350,7 @@ class SettingsProvider extends ChangeNotifier {
AccentColor? accentColor, AccentColor? accentColor,
List<Color>? gradeColors, List<Color>? gradeColors,
bool? newsEnabled, bool? newsEnabled,
int? newsState, String? seenNewsId,
bool? notificationsEnabled, bool? notificationsEnabled,
int? notificationsBitfield, int? notificationsBitfield,
bool? developerMode, bool? developerMode,
@ -391,7 +393,11 @@ class SettingsProvider extends ChangeNotifier {
if (newsEnabled != null && newsEnabled != _newsEnabled) { if (newsEnabled != null && newsEnabled != _newsEnabled) {
_newsEnabled = newsEnabled; _newsEnabled = newsEnabled;
} }
if (newsState != null && newsState != _newsState) _newsState = newsState; if (seenNewsId != null && !_seenNews.split(',').contains(seenNewsId)) {
var tempList = _seenNews.split(',');
tempList.add(seenNewsId);
_seenNews = tempList.join(',');
}
if (notificationsEnabled != null && if (notificationsEnabled != null &&
notificationsEnabled != _notificationsEnabled) { notificationsEnabled != _notificationsEnabled) {
_notificationsEnabled = notificationsEnabled; _notificationsEnabled = notificationsEnabled;

View File

@ -139,7 +139,6 @@ class NavigationScreenState extends State<NavigationScreen>
void initState() { void initState() {
super.initState(); super.initState();
HomeWidget.setAppGroupId('hu.refilc.naplo.group'); HomeWidget.setAppGroupId('hu.refilc.naplo.group');
_checkForWidgetLaunch(); _checkForWidgetLaunch();
@ -199,9 +198,9 @@ class NavigationScreenState extends State<NavigationScreen>
// Show news // Show news
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
if (newsProvider.show) { if (newsProvider.show) {
newsProvider.lock(); NewsView.show(newsProvider.news[0], context: context)
NewsView.show(newsProvider.news[newsProvider.state], context: context)
.then((value) => newsProvider.release()); .then((value) => newsProvider.release());
newsProvider.lock();
} }
}); });

View File

@ -31,23 +31,30 @@ class NewsView extends StatelessWidget {
physics: const BouncingScrollPhysics(), physics: const BouncingScrollPhysics(),
children: [ children: [
Padding( Padding(
padding: const EdgeInsets.only(left: 8.0, right: 6.0, top: 14.0, bottom: 8.0), padding: const EdgeInsets.only(
left: 8.0, right: 6.0, top: 14.0, bottom: 8.0),
child: Text( child: Text(
news.title, news.title,
maxLines: 3, maxLines: 3,
style: const TextStyle(fontWeight: FontWeight.w600, fontSize: 18.0), style: const TextStyle(
fontWeight: FontWeight.w600, fontSize: 18.0),
), ),
), ),
SelectableLinkify( SelectableLinkify(
text: news.content.escapeHtml(), text: news.content.escapeHtml(),
options: const LinkifyOptions(looseUrl: true, removeWww: true), options:
const LinkifyOptions(looseUrl: true, removeWww: true),
onOpen: (link) { onOpen: (link) {
launch( launch(
link.url, link.url,
customTabsOption: CustomTabsOption(showPageTitle: true, toolbarColor: Theme.of(context).scaffoldBackgroundColor), customTabsOption: CustomTabsOption(
showPageTitle: true,
toolbarColor:
Theme.of(context).scaffoldBackgroundColor),
); );
}, },
style: const TextStyle(fontWeight: FontWeight.w500, fontSize: 14.0), style: const TextStyle(
fontWeight: FontWeight.w500, fontSize: 14.0),
), ),
], ],
), ),
@ -59,10 +66,15 @@ class NewsView extends StatelessWidget {
children: [ children: [
if (news.link != "") if (news.link != "")
DialogButton( DialogButton(
label: news.openLabel != "" ? news.openLabel : "open".i18n.toUpperCase(), label: news.openLabel != ""
? news.openLabel
: "open".i18n.toUpperCase(),
onTap: () => launch( onTap: () => launch(
news.link, news.link,
customTabsOption: CustomTabsOption(showPageTitle: true, toolbarColor: Theme.of(context).scaffoldBackgroundColor), customTabsOption: CustomTabsOption(
showPageTitle: true,
toolbarColor:
Theme.of(context).scaffoldBackgroundColor),
), ),
), ),
DialogButton( DialogButton(
@ -78,12 +90,15 @@ class NewsView extends StatelessWidget {
); );
} }
static Future<T?> show<T>(News news, {required BuildContext context, bool force = false}) { static Future<T?> show<T>(News news,
{required BuildContext context, bool force = false}) {
if (news.title == "") return Future<T?>.value(null); if (news.title == "") return Future<T?>.value(null);
bool popup = news.platform == '' || force; bool popup = news.platform == 'all' || force;
if (Provider.of<SettingsProvider>(context, listen: false).newsEnabled || news.emergency || force) { if (Provider.of<SettingsProvider>(context, listen: false).newsEnabled ||
news.emergency ||
force) {
switch (news.platform.trim().toLowerCase()) { switch (news.platform.trim().toLowerCase()) {
case "android": case "android":
if (Platform.isAndroid) popup = true; if (Platform.isAndroid) popup = true;
@ -100,6 +115,9 @@ class NewsView extends StatelessWidget {
case "macos": case "macos":
if (Platform.isMacOS) popup = true; if (Platform.isMacOS) popup = true;
break; break;
case "all":
popup = true;
break;
default: default:
popup = true; popup = true;
} }
@ -108,7 +126,10 @@ class NewsView extends StatelessWidget {
} }
if (popup) { if (popup) {
return showDialog<T?>(context: context, builder: (context) => NewsView(news), barrierDismissible: true); return showDialog<T?>(
context: context,
builder: (context) => NewsView(news),
barrierDismissible: true);
} else { } else {
return Future<T?>.value(null); return Future<T?>.value(null);
} }