initial
This commit is contained in:
83
lib/appflow/controller/articles.dart
Normal file
83
lib/appflow/controller/articles.dart
Normal file
@@ -0,0 +1,83 @@
|
||||
import 'package:hiddingsel_app/appflow/controller/network/wordpress.dart';
|
||||
import 'package:hiddingsel_app/appflow/model/articles.dart';
|
||||
import 'package:hiddingsel_app/appflow/model/represented_organisations.dart';
|
||||
import 'package:hiddingsel_app/constants/constant.dart';
|
||||
|
||||
import '../../services/storage.dart';
|
||||
|
||||
class ArticleController {
|
||||
|
||||
static int defaultSortCompare(ArticleModel a, ArticleModel b) => b.publishedAt.compareTo(a.publishedAt);
|
||||
|
||||
static Stream<List<ArticleModel>> getArticleListStream({int Function(ArticleModel, ArticleModel) sortCompare = defaultSortCompare}) async*{
|
||||
|
||||
List<ArticleModel> yieldArticles = [];
|
||||
List<ArticleModel> allWordpressArticles = [];
|
||||
List<ArticleModel> savedArticles = await DataConnector.getJsonEncodableList<ArticleModel>(SystemStrings.dataArticles, [], ArticleModel.fromJson);
|
||||
yield yieldArticles..addAll(savedArticles)..sort(sortCompare);
|
||||
|
||||
for (var page = 0, perPage = 10; page < 10; page++) {
|
||||
var wordpressArticles = await WordpressController.getArticles(page, perPage);
|
||||
var newWordpressArticles = wordpressArticles.where((a) => !yieldArticles.contains(a)).toList();
|
||||
if (newWordpressArticles.isNotEmpty) {
|
||||
yield yieldArticles..addAll(newWordpressArticles)..sort(sortCompare);
|
||||
}
|
||||
allWordpressArticles = allWordpressArticles..addAll(wordpressArticles)..sort(sortCompare);
|
||||
DataConnector.saveJsonEncodable(SystemStrings.dataArticles, allWordpressArticles);
|
||||
}
|
||||
}
|
||||
|
||||
static Stream<List<ArticleModel>> getSearchResultListStream(String searchWord, {int Function(ArticleModel, ArticleModel) sortCompare = defaultSortCompare}) async*{
|
||||
|
||||
List<ArticleModel> yieldArticles = [];
|
||||
for (var page = 0, perPage = 10; page < 3; page++) {
|
||||
var wordpressArticles = await WordpressController.searchArticles(page, perPage, searchWord);
|
||||
var newWordpressArticles = wordpressArticles.where((a) => !yieldArticles.contains(a)).toList();
|
||||
if (newWordpressArticles.isNotEmpty) {
|
||||
yield yieldArticles..addAll(newWordpressArticles)..sort(sortCompare);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static Stream<List<ArticleModel>> getOrganisationArticleListStream(RepresentedOrganisationModel organisation, {int Function(ArticleModel, ArticleModel) sortCompare = defaultSortCompare}) async*{
|
||||
|
||||
List<ArticleModel> yieldArticles = [];
|
||||
List<ArticleModel> allWordpressArticles = [];
|
||||
List<ArticleModel> savedArticles = await DataConnector.getJsonEncodableList<ArticleModel>(SystemStrings.dataArticles + organisation.id, [], ArticleModel.fromJson);
|
||||
yield yieldArticles..addAll(savedArticles)..sort(sortCompare);
|
||||
|
||||
for (var page = 0, perPage = 10; page < 10; page++) {
|
||||
var wordpressArticles = await WordpressController.getArticlesFromOrganisations(page, perPage, [organisation]);
|
||||
var newWordpressArticles = wordpressArticles.where((a) => !yieldArticles.contains(a)).toList();
|
||||
if (newWordpressArticles.isNotEmpty) {
|
||||
yield yieldArticles..addAll(newWordpressArticles)..sort(sortCompare);
|
||||
}
|
||||
allWordpressArticles = allWordpressArticles..addAll(wordpressArticles)..sort(sortCompare);
|
||||
DataConnector.saveJsonEncodable(SystemStrings.dataArticles + organisation.id, allWordpressArticles);
|
||||
}
|
||||
}
|
||||
|
||||
static Stream<List<ArticleModel>> getFavoriteArticleListStream({int Function(ArticleModel, ArticleModel) sortCompare = defaultSortCompare}) async*{
|
||||
|
||||
var favoriteOrganisations = List<RepresentedOrganisationModel>.empty(growable: true);
|
||||
for (RepresentedOrganisationModel organisation in RepresentedOrganisationModel.values) {
|
||||
if(await organisation.favorized) favoriteOrganisations.add(organisation);
|
||||
}
|
||||
|
||||
List<ArticleModel> yieldArticles = [];
|
||||
List<ArticleModel> allWordpressArticles = [];
|
||||
List<ArticleModel> savedArticles = await DataConnector.getJsonEncodableList<ArticleModel>(SystemStrings.dataFavoriteArticles, [], ArticleModel.fromJson);
|
||||
List<ArticleModel> savedFavoriteArticles = savedArticles.where((e) => e.categories.any((orga) => favoriteOrganisations.contains(orga))).toList();
|
||||
yield yieldArticles..addAll(savedFavoriteArticles)..sort(sortCompare);
|
||||
|
||||
for (var page = 0, perPage = 10; page < 10; page++) {
|
||||
var wordpressArticles = await WordpressController.getArticlesFromOrganisations(page, perPage, favoriteOrganisations);
|
||||
var newWordpressArticles = wordpressArticles.where((a) => !yieldArticles.contains(a)).toList();
|
||||
if (newWordpressArticles.isNotEmpty) {
|
||||
yield yieldArticles..addAll(newWordpressArticles)..sort(sortCompare);
|
||||
}
|
||||
allWordpressArticles = allWordpressArticles..addAll(wordpressArticles)..sort(sortCompare);
|
||||
DataConnector.saveJsonEncodable(SystemStrings.dataFavoriteArticles, allWordpressArticles);
|
||||
}
|
||||
}
|
||||
}
|
||||
68
lib/appflow/controller/events.dart
Normal file
68
lib/appflow/controller/events.dart
Normal file
@@ -0,0 +1,68 @@
|
||||
import 'package:hiddingsel_app/appflow/controller/network/calendar.dart';
|
||||
import 'package:hiddingsel_app/appflow/model/event.dart';
|
||||
import 'package:hiddingsel_app/appflow/model/event_organisations.dart';
|
||||
|
||||
import '../../constants/constant.dart';
|
||||
import '../../services/storage.dart';
|
||||
import '../../todo/scheduled_notification.dart';
|
||||
|
||||
class EventController {
|
||||
|
||||
static int defaultSortCompare(EventModel a, EventModel b) => a.schedule.startTime.compareTo(b.schedule.startTime);
|
||||
|
||||
static Stream<List<EventModel>> getEventListStream({int Function(EventModel, EventModel) sortCompare = defaultSortCompare}) async* {
|
||||
List<EventModel> yieldEvents = [];
|
||||
List<EventModel> allEvents = [];
|
||||
List<EventModel> newEvents = [];
|
||||
List<EventModel> organisationEvents = [];
|
||||
List<EventModel> savedEvents = await DataConnector.getJsonEncodableList<
|
||||
EventModel>(SystemStrings.dataEvents, [], EventModel.fromJson);
|
||||
yield yieldEvents = yieldEvents..addAll(savedEvents)..sort(sortCompare);
|
||||
|
||||
for (EventOrganisationModel eventOrganisation in EventOrganisationModel.values){
|
||||
organisationEvents = await CalendarController
|
||||
.getOrganisationEvents(eventOrganisation);
|
||||
newEvents = organisationEvents.where((a) => !yieldEvents.contains(a)).toList();
|
||||
if (newEvents.isNotEmpty) {
|
||||
yield yieldEvents
|
||||
..addAll(newEvents)
|
||||
..sort(sortCompare);
|
||||
}
|
||||
allEvents = allEvents..addAll(organisationEvents)..sort(sortCompare);
|
||||
}
|
||||
DataConnector.saveJsonEncodable(SystemStrings.dataEvents, allEvents);
|
||||
}
|
||||
|
||||
static Future<void> scheduleNotificationsBySettings() async {
|
||||
List<EventOrganisationModel> notifiableOrganisations = await _getNotifiableOrganisations();
|
||||
final duration = Duration(milliseconds: await SettingsConnector.getInt(SystemStrings.keyAlertTime, 1*60*60*1000));
|
||||
await ScheduledNotificationConnector.cancelAllScheduledNotification();
|
||||
EventController.getEventListStream().forEach((List<EventModel> list) async{
|
||||
var eventsToSchedule = list
|
||||
.where((e) => e.schedule.startTime.isAfter(DateTime.now()))
|
||||
.where((e) => notifiableOrganisations.any((o) => e.eventOrganizer.contains(o)))
|
||||
.toList();
|
||||
_scheduleNotifications(eventsToSchedule, duration);
|
||||
});
|
||||
}
|
||||
|
||||
static _getNotifiableOrganisations() async {
|
||||
var notifiableOrganisations = List<EventOrganisationModel>.empty(growable: true);
|
||||
for (EventOrganisationModel event in EventOrganisationModel.values) {
|
||||
if(await event.eventNotificationAllowed) notifiableOrganisations.add(event);
|
||||
}
|
||||
return notifiableOrganisations;
|
||||
}
|
||||
|
||||
static _scheduleNotifications(List<EventModel> eventsToSchedule,
|
||||
Duration duration) {
|
||||
eventsToSchedule.sort((a, b) => a.schedule.startTime.compareTo(b.schedule.startTime));
|
||||
Future.forEach(eventsToSchedule.take(50), (EventModel element) async {
|
||||
ScheduledNotificationConnector.scheduleNotification(
|
||||
element.id.hashCode,
|
||||
element.schedule.startTime.subtract(duration),
|
||||
element.name,
|
||||
'${element.eventOrganizer.first.name} - Der Termin beginnt bald.');
|
||||
});
|
||||
}
|
||||
}
|
||||
65
lib/appflow/controller/initial_start.dart
Normal file
65
lib/appflow/controller/initial_start.dart
Normal file
@@ -0,0 +1,65 @@
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:hiddingsel_app/appflow/controller/events.dart';
|
||||
import 'package:hiddingsel_app/appflow/model/pois.dart';
|
||||
import 'package:hiddingsel_app/appflow/model/represented_organisations.dart';
|
||||
import 'package:hiddingsel_app/constants/constant.dart';
|
||||
import 'package:hiddingsel_app/appflow/model/event_organisations.dart';
|
||||
import 'package:hiddingsel_app/services/storage.dart';
|
||||
import 'package:hiddingsel_app/todo/scheduled_notification.dart';
|
||||
|
||||
import '../model/companies.dart';
|
||||
import '../model/topics.dart';
|
||||
import '../../services/notification.dart';
|
||||
import 'package:timezone/data/latest_all.dart' as tz;
|
||||
|
||||
class InitialStartController {
|
||||
|
||||
static Future<void> ensureInitialized() async {
|
||||
await initializeAlways();
|
||||
|
||||
SettingsConnector.getBool(SystemStrings.keyFirstTime, true).then((firstTime)
|
||||
{if(firstTime) {
|
||||
initializeFirstTime();
|
||||
SettingsConnector.setBool(SystemStrings.keyFirstTime, false);
|
||||
}});
|
||||
}
|
||||
|
||||
static Future<void> initializeAlways() async {
|
||||
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
|
||||
statusBarColor: UIColors.white,
|
||||
statusBarIconBrightness: Brightness.dark,
|
||||
statusBarBrightness: Brightness.light,
|
||||
));
|
||||
|
||||
//RemoteConfigConnector.initialize();
|
||||
ExternalNotificationConnector.initialize();
|
||||
await ScheduledNotificationConnector.initialize();
|
||||
tz.initializeTimeZones();
|
||||
|
||||
await load<PointOfInterestModel>(SystemStrings.assetPois, PointOfInterestModel.fromJson);
|
||||
await load<CompanyModel>(SystemStrings.assetCompanies, CompanyModel.fromJson);
|
||||
await load<RepresentedOrganisationModel>(SystemStrings.assetRepresentedOrganisations, RepresentedOrganisationModel.fromJson);
|
||||
await load<EventOrganisationModel>(SystemStrings.assetEventOrganisations, EventOrganisationModel.fromJson);
|
||||
await load<PushNotificationTopicModel>(SystemStrings.assetTopics, PushNotificationTopicModel.fromJson);
|
||||
|
||||
EventController.scheduleNotificationsBySettings();
|
||||
}
|
||||
|
||||
static Future<void> load<T>(asset, fromJson) async {
|
||||
final jsonData = await AssetConnector.getJson(asset);
|
||||
List<T> list = jsonData.map((json) => fromJson(json)).toList().cast<T>();
|
||||
GetIt.I.registerSingleton<List<T>>(list);
|
||||
}
|
||||
|
||||
static void initializeFirstTime() async {
|
||||
PushNotificationTopicModel.values.forEach((e) => e.subscribe(false));
|
||||
CompanyModel.values.forEach((e) => e.subscribe(false));
|
||||
RepresentedOrganisationModel.values.forEach((e) => e.favorize(false));
|
||||
EventOrganisationModel.values.forEach((e) => e.allowEventNotification(false));
|
||||
EventOrganisationModel.values.where((e) => e.id == "garbage").forEach((e) => e.allowEventNotification(true));
|
||||
EventOrganisationModel.values.where((e) => e.id == "dorfgemeinschaft").forEach((e) => e.allowEventNotification(true));
|
||||
EventController.scheduleNotificationsBySettings();
|
||||
}
|
||||
}
|
||||
21
lib/appflow/controller/network/calendar.dart
Normal file
21
lib/appflow/controller/network/calendar.dart
Normal file
@@ -0,0 +1,21 @@
|
||||
import 'package:hiddingsel_app/appflow/model/event_organisations.dart';
|
||||
|
||||
import '../../../services/network.dart';
|
||||
import '../../../todo/parser.dart';
|
||||
import '../../model/event.dart';
|
||||
import 'package:http/http.dart';
|
||||
import 'dart:convert' show utf8;
|
||||
|
||||
class CalendarController {
|
||||
|
||||
static Future<List<EventModel>> getOrganisationEvents(EventOrganisationModel eventOrganisation) {
|
||||
if(eventOrganisation.ical == null) return Future.value(List<EventModel>.empty());
|
||||
return BaseService.getSaveFromServer(
|
||||
() => _getEvents(eventOrganisation.ical), List<EventModel>.empty());
|
||||
}
|
||||
|
||||
static Future<List<EventModel>> _getEvents(icalUri) async {
|
||||
final response = await get(icalUri);
|
||||
return IcalParser.parse(utf8.decode(response.bodyBytes));
|
||||
}
|
||||
}
|
||||
64
lib/appflow/controller/network/wordpress.dart
Normal file
64
lib/appflow/controller/network/wordpress.dart
Normal file
@@ -0,0 +1,64 @@
|
||||
import 'dart:convert';
|
||||
import 'package:hiddingsel_app/appflow/model/represented_organisations.dart';
|
||||
|
||||
import '../../../services/network.dart';
|
||||
import '../../model/articles.dart';
|
||||
import 'package:http/http.dart';
|
||||
|
||||
class WordpressController {
|
||||
|
||||
static const String _baseUrl = 'www.hiddingsel.de';
|
||||
static const String _path = 'wp-json/wp/v2/posts';
|
||||
static const String _parameterPage = 'page';
|
||||
static const String _parameterPerPage = 'per_page';
|
||||
static const String _parameterSearch = 'search';
|
||||
static const String _parameterCategories = 'categories';
|
||||
static const String _parameterEmbed = '_embed';
|
||||
static const int _httpCodeKeineWeiterenArticel = 400;
|
||||
|
||||
static Future<List<ArticleModel>> getArticles(int page, int itemCount) =>
|
||||
BaseService.getSaveFromServer(
|
||||
() => _getArticles(page, itemCount),
|
||||
List<ArticleModel>.empty()
|
||||
);
|
||||
|
||||
static Future<List<ArticleModel>> searchArticles(int page, int itemCount, String searchWord) =>
|
||||
BaseService.getSaveFromServer(
|
||||
() => _getArticles(page, itemCount, searchWord: searchWord),
|
||||
List<ArticleModel>.empty()
|
||||
);
|
||||
|
||||
static Future<List<ArticleModel>> getArticlesFromOrganisations(int page, int itemCount, List<RepresentedOrganisationModel> organisations) =>
|
||||
BaseService.getSaveFromServer(
|
||||
() => _getArticles(page, itemCount, organisations: organisations),
|
||||
List<ArticleModel>.empty()
|
||||
);
|
||||
|
||||
static Future<List<ArticleModel>> _getArticles(int page, int itemCount, {String? searchWord, List<RepresentedOrganisationModel>? organisations}) async {
|
||||
|
||||
final parameters = <String, dynamic> {
|
||||
_parameterPage: (page + 1).toString(),
|
||||
_parameterPerPage: itemCount.toString(),
|
||||
_parameterSearch: searchWord,
|
||||
_parameterCategories: organisations?.map((e) => e.wordpressId).join(','),
|
||||
_parameterEmbed: null,
|
||||
};
|
||||
|
||||
if(searchWord?.isEmpty ?? true) {
|
||||
parameters.remove(_parameterSearch);
|
||||
}
|
||||
if(organisations?.isEmpty ?? true) {
|
||||
parameters.remove(_parameterCategories);
|
||||
}
|
||||
|
||||
final uri = Uri.https(_baseUrl, _path, parameters);
|
||||
final response = await get(uri);
|
||||
|
||||
if (response.statusCode == _httpCodeKeineWeiterenArticel) {
|
||||
return [];
|
||||
}
|
||||
|
||||
final jsonData = json.decode(response.body);
|
||||
return jsonData.map((article) => ArticleModel.fromWordpressJson(article)).cast<ArticleModel>().toList();
|
||||
}
|
||||
}
|
||||
45
lib/appflow/controller/settings.dart
Normal file
45
lib/appflow/controller/settings.dart
Normal file
@@ -0,0 +1,45 @@
|
||||
import 'package:hiddingsel_app/appflow/model/event_organisations.dart';
|
||||
import 'package:hiddingsel_app/appflow/model/topics.dart';
|
||||
import 'package:hiddingsel_app/services/storage.dart';
|
||||
|
||||
import '../../constants/constant.dart';
|
||||
import 'events.dart';
|
||||
|
||||
class SettingsController {
|
||||
|
||||
static const subscribtion = SystemStrings.keyPreSubscribtion;
|
||||
static const eventNotification = SystemStrings.keyPreEventNotification;
|
||||
static const favorization = SystemStrings.keyPreFavorization;
|
||||
|
||||
static void subscribeTopic(PushNotificationTopicModel topic) =>
|
||||
SettingsConnector.setBool(subscribtion + topic.id, true);
|
||||
|
||||
static void unsubscribeTopic(PushNotificationTopicModel topic) =>
|
||||
SettingsConnector.setBool(subscribtion + topic.id, false);
|
||||
|
||||
static Future<bool> subscribed(PushNotificationTopicModel topic) =>
|
||||
SettingsConnector.getBool(subscribtion + topic.id, false);
|
||||
|
||||
static void allowEventNotification(EventOrganisationModel eventOrganisation) async {
|
||||
await SettingsConnector.setBool(eventNotification + eventOrganisation.id, true);
|
||||
EventController.scheduleNotificationsBySettings();
|
||||
}
|
||||
|
||||
|
||||
static void unallowEventNotification(EventOrganisationModel eventOrganisation) async {
|
||||
await SettingsConnector.setBool(eventNotification + eventOrganisation.id, false);
|
||||
EventController.scheduleNotificationsBySettings();
|
||||
}
|
||||
|
||||
static Future<bool> eventNotificationAllowed(EventOrganisationModel eventOrganisation) =>
|
||||
SettingsConnector.getBool(eventNotification + eventOrganisation.id, false);
|
||||
|
||||
static void favorize(PushNotificationTopicModel topic) =>
|
||||
SettingsConnector.setBool(favorization + topic.id, true);
|
||||
|
||||
static void unfavorize(PushNotificationTopicModel topic) =>
|
||||
SettingsConnector.setBool(favorization + topic.id, false);
|
||||
|
||||
static Future<bool> favorized(PushNotificationTopicModel topic) =>
|
||||
SettingsConnector.getBool(favorization + topic.id, false);
|
||||
}
|
||||
Reference in New Issue
Block a user