diff --git a/.travis.yml b/.travis.yml
index a147c08..b9665b6 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -5,7 +5,7 @@ addons:
packages:
- lib32stdc++6
install:
- - git clone --depth 1 --branch 1.22.0 https://github.com/flutter/flutter.git
+ - git clone --depth 1 --branch 2.10.2 https://github.com/flutter/flutter.git
- ./flutter/bin/flutter doctor
- gem install coveralls-lcov
- cp .env.example .env
diff --git a/android/app/build.gradle b/android/app/build.gradle
index e38ba2a..be5b94e 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -48,6 +48,7 @@ android {
applicationId "net.lucien144.fyx"
minSdkVersion 19
targetSdkVersion 31
+ //multiDexEnabled true // Uncomment for dev
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index efe69ad..046d749 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -13,6 +13,9 @@
android:label="fyx"
android:requestLegacyExternalStorage="true"
android:icon="@mipmap/ic_launcher">
+
8.0)
- GoogleUtilities/Environment (~> 7.6)
- GoogleUtilities/Logger (~> 7.6)
- - FirebaseCoreDiagnostics (8.10.0):
+ - FirebaseCoreDiagnostics (8.15.0):
- GoogleDataTransport (~> 9.1)
- - GoogleUtilities/Environment (~> 7.6)
- - GoogleUtilities/Logger (~> 7.6)
+ - GoogleUtilities/Environment (~> 7.7)
+ - GoogleUtilities/Logger (~> 7.7)
- nanopb (~> 2.30908.0)
- - FirebaseInstallations (8.10.0):
+ - FirebaseInstallations (8.15.0):
- FirebaseCore (~> 8.0)
- - GoogleUtilities/Environment (~> 7.6)
- - GoogleUtilities/UserDefaults (~> 7.6)
+ - GoogleUtilities/Environment (~> 7.7)
+ - GoogleUtilities/UserDefaults (~> 7.7)
- PromisesObjC (< 3.0, >= 1.2)
- FirebaseMessaging (8.9.0):
- FirebaseCore (~> 8.0)
@@ -94,28 +94,28 @@ PODS:
- GoogleUtilities/Environment (~> 7.2)
- nanopb (~> 2.30908.0)
- PromisesObjC (< 3.0, >= 1.2)
- - GoogleUtilities/AppDelegateSwizzler (7.6.0):
+ - GoogleUtilities/AppDelegateSwizzler (7.7.0):
- GoogleUtilities/Environment
- GoogleUtilities/Logger
- GoogleUtilities/Network
- - GoogleUtilities/Environment (7.6.0):
+ - GoogleUtilities/Environment (7.7.0):
- PromisesObjC (< 3.0, >= 1.2)
- - GoogleUtilities/Logger (7.6.0):
+ - GoogleUtilities/Logger (7.7.0):
- GoogleUtilities/Environment
- - GoogleUtilities/MethodSwizzler (7.6.0):
+ - GoogleUtilities/MethodSwizzler (7.7.0):
- GoogleUtilities/Logger
- - GoogleUtilities/Network (7.6.0):
+ - GoogleUtilities/Network (7.7.0):
- GoogleUtilities/Logger
- "GoogleUtilities/NSData+zlib"
- GoogleUtilities/Reachability
- - "GoogleUtilities/NSData+zlib (7.6.0)"
- - GoogleUtilities/Reachability (7.6.0):
+ - "GoogleUtilities/NSData+zlib (7.7.0)"
+ - GoogleUtilities/Reachability (7.7.0):
- GoogleUtilities/Logger
- - GoogleUtilities/UserDefaults (7.6.0):
+ - GoogleUtilities/UserDefaults (7.7.0):
- GoogleUtilities/Logger
- image_gallery_saver (1.5.0):
- Flutter
- - image_picker (0.0.1):
+ - image_picker_ios (0.0.1):
- Flutter
- nanopb (2.30908.0):
- nanopb/decode (= 2.30908.0)
@@ -126,29 +126,29 @@ PODS:
- Flutter
- package_info_plus (0.4.5):
- Flutter
- - path_provider (0.0.1):
+ - path_provider_ios (0.0.1):
- Flutter
- - "permission_handler (5.1.0+2)":
+ - permission_handler_apple (9.0.4):
- Flutter
- - PromisesObjC (2.0.0)
- - Sentry (7.5.4):
- - Sentry/Core (= 7.5.4)
- - Sentry/Core (7.5.4)
+ - PromisesObjC (2.1.0)
+ - Sentry (7.9.0):
+ - Sentry/Core (= 7.9.0)
+ - Sentry/Core (7.9.0)
- sentry_flutter (0.0.1):
- Flutter
- FlutterMacOS
- - Sentry (~> 7.5.1)
+ - Sentry (~> 7.9.0)
- share (0.0.1):
- Flutter
- - shared_preferences (0.0.1):
+ - shared_preferences_ios (0.0.1):
- Flutter
- sqflite (0.0.2):
- Flutter
- FMDB (>= 2.7.5)
- Toast (4.0.0)
- - url_launcher (0.0.1):
+ - url_launcher_ios (0.0.1):
- Flutter
- - video_player (0.0.1):
+ - video_player_avfoundation (0.0.1):
- Flutter
- wakelock (0.0.1):
- Flutter
@@ -163,17 +163,17 @@ DEPENDENCIES:
- Flutter (from `Flutter`)
- fluttertoast (from `.symlinks/plugins/fluttertoast/ios`)
- image_gallery_saver (from `.symlinks/plugins/image_gallery_saver/ios`)
- - image_picker (from `.symlinks/plugins/image_picker/ios`)
+ - image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
- package_info (from `.symlinks/plugins/package_info/ios`)
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
- - path_provider (from `.symlinks/plugins/path_provider/ios`)
- - permission_handler (from `.symlinks/plugins/permission_handler/ios`)
+ - path_provider_ios (from `.symlinks/plugins/path_provider_ios/ios`)
+ - permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
- sentry_flutter (from `.symlinks/plugins/sentry_flutter/ios`)
- share (from `.symlinks/plugins/share/ios`)
- - shared_preferences (from `.symlinks/plugins/shared_preferences/ios`)
+ - shared_preferences_ios (from `.symlinks/plugins/shared_preferences_ios/ios`)
- sqflite (from `.symlinks/plugins/sqflite/ios`)
- - url_launcher (from `.symlinks/plugins/url_launcher/ios`)
- - video_player (from `.symlinks/plugins/video_player/ios`)
+ - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
+ - video_player_avfoundation (from `.symlinks/plugins/video_player_avfoundation/ios`)
- wakelock (from `.symlinks/plugins/wakelock/ios`)
- webview_flutter (from `.symlinks/plugins/webview_flutter/ios`)
@@ -209,28 +209,28 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/fluttertoast/ios"
image_gallery_saver:
:path: ".symlinks/plugins/image_gallery_saver/ios"
- image_picker:
- :path: ".symlinks/plugins/image_picker/ios"
+ image_picker_ios:
+ :path: ".symlinks/plugins/image_picker_ios/ios"
package_info:
:path: ".symlinks/plugins/package_info/ios"
package_info_plus:
:path: ".symlinks/plugins/package_info_plus/ios"
- path_provider:
- :path: ".symlinks/plugins/path_provider/ios"
- permission_handler:
- :path: ".symlinks/plugins/permission_handler/ios"
+ path_provider_ios:
+ :path: ".symlinks/plugins/path_provider_ios/ios"
+ permission_handler_apple:
+ :path: ".symlinks/plugins/permission_handler_apple/ios"
sentry_flutter:
:path: ".symlinks/plugins/sentry_flutter/ios"
share:
:path: ".symlinks/plugins/share/ios"
- shared_preferences:
- :path: ".symlinks/plugins/shared_preferences/ios"
+ shared_preferences_ios:
+ :path: ".symlinks/plugins/shared_preferences_ios/ios"
sqflite:
:path: ".symlinks/plugins/sqflite/ios"
- url_launcher:
- :path: ".symlinks/plugins/url_launcher/ios"
- video_player:
- :path: ".symlinks/plugins/video_player/ios"
+ url_launcher_ios:
+ :path: ".symlinks/plugins/url_launcher_ios/ios"
+ video_player_avfoundation:
+ :path: ".symlinks/plugins/video_player_avfoundation/ios"
wakelock:
:path: ".symlinks/plugins/wakelock/ios"
webview_flutter:
@@ -244,31 +244,31 @@ SPEC CHECKSUMS:
firebase_messaging: dff5cd08781ee1de988565a83c977e435405cd7e
FirebaseAnalytics: 4ab446ce08a3fe52e8a4303dd997cf26276bf968
FirebaseCore: 599ee609343eaf4941bd188f85e3aa077ffe325b
- FirebaseCoreDiagnostics: 56fb7216d87e0e6ec2feddefa9d8a392fe8b2c18
- FirebaseInstallations: 830327b45345ffc859eaa9c17bcd5ae893fd5425
+ FirebaseCoreDiagnostics: 92e07a649aeb66352b319d43bdd2ee3942af84cb
+ FirebaseInstallations: 40bd9054049b2eae9a2c38ef1c3dd213df3605cd
FirebaseMessaging: 82c4a48638f53f7b184f3cc9f6cd2cbe533ab316
Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a
- fluttertoast: 6122fa75143e992b1d3470f61000f591a798cc58
+ fluttertoast: 16fbe6039d06a763f3533670197d01fc73459037
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
GoogleAppMeasurement: 837649ad3987936c232f6717c5680216f6243d24
GoogleDataTransport: 629c20a4d363167143f30ea78320d5a7eb8bd940
- GoogleUtilities: 684ee790a24f73ebb2d1d966e9711c203f2a4237
+ GoogleUtilities: e0913149f6b0625b553d70dae12b49fc62914fd1
image_gallery_saver: 259eab68fb271cfd57d599904f7acdc7832e7ef2
- image_picker: 9aa50e1d8cdacdbed739e925b7eea16d014367e6
+ image_picker_ios: b786a5dcf033a8336a657191401bfdf12017dabb
nanopb: a0ba3315591a9ae0a16a309ee504766e90db0c96
package_info: 873975fc26034f0b863a300ad47e7f1ac6c7ec62
package_info_plus: 6c92f08e1f853dc01228d6f553146438dafcd14e
- path_provider: d1e9807085df1f9cc9318206cd649dc0b76be3de
- permission_handler: ccb20a9fad0ee9b1314a52b70b76b473c5f8dab0
- PromisesObjC: 68159ce6952d93e17b2dfe273b8c40907db5ba58
- Sentry: 5c5dd4005f3b7b9765d5a8871232cddbd0d888b7
- sentry_flutter: 4cd99764f9fe01c9415790d1f3fb1c7fd3a5cbe9
+ path_provider_ios: 7d7ce634493af4477d156294792024ec3485acd5
+ permission_handler_apple: 44366e37eaf29454a1e7b1b7d736c2cceaeb17ce
+ PromisesObjC: 99b6f43f9e1044bd87a95a60beff28c2c44ddb72
+ Sentry: 2f7e91f247cfb05b05bd01e0b5d0692557a7687b
+ sentry_flutter: 7c3cb050dc23563a4ea5db438c83afdb460a2ae6
share: 0b2c3e82132f5888bccca3351c504d0003b3b410
- shared_preferences: af6bfa751691cdc24be3045c43ec037377ada40d
+ shared_preferences_ios: 548a61f8053b9b8a49ac19c1ffbc8b92c50d68ad
sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904
Toast: 91b396c56ee72a5790816f40d3a94dd357abc196
- url_launcher: 6fef411d543ceb26efce54b05a0a40bfd74cbbef
- video_player: ecd305f42e9044793efd34846e1ce64c31ea6fcb
+ url_launcher_ios: 839c58cdb4279282219f5e248c3321761ff3c4de
+ video_player_avfoundation: e489aac24ef5cf7af82702979ed16f2a5ef84cff
wakelock: d0fc7c864128eac40eba1617cb5264d9c940b46f
webview_flutter: 3603125dfd3bcbc9d8d418c3f80aeecf331c068b
diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj
index 1403839..821fde7 100644
--- a/ios/Runner.xcodeproj/project.pbxproj
+++ b/ios/Runner.xcodeproj/project.pbxproj
@@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
- objectVersion = 46;
+ objectVersion = 50;
objects = {
/* Begin PBXBuildFile section */
@@ -168,7 +168,7 @@
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
- LastUpgradeCheck = 1130;
+ LastUpgradeCheck = 1300;
ORGANIZATIONNAME = "The Chromium Authors";
TargetAttributes = {
97C146ED1CF9000F007C117D = {
@@ -268,17 +268,17 @@
"${BUILT_PRODUCTS_DIR}/device_info/device_info.framework",
"${BUILT_PRODUCTS_DIR}/fluttertoast/fluttertoast.framework",
"${BUILT_PRODUCTS_DIR}/image_gallery_saver/image_gallery_saver.framework",
- "${BUILT_PRODUCTS_DIR}/image_picker/image_picker.framework",
+ "${BUILT_PRODUCTS_DIR}/image_picker_ios/image_picker_ios.framework",
"${BUILT_PRODUCTS_DIR}/nanopb/nanopb.framework",
"${BUILT_PRODUCTS_DIR}/package_info/package_info.framework",
"${BUILT_PRODUCTS_DIR}/package_info_plus/package_info_plus.framework",
- "${BUILT_PRODUCTS_DIR}/path_provider/path_provider.framework",
+ "${BUILT_PRODUCTS_DIR}/path_provider_ios/path_provider_ios.framework",
"${BUILT_PRODUCTS_DIR}/sentry_flutter/sentry_flutter.framework",
"${BUILT_PRODUCTS_DIR}/share/share.framework",
- "${BUILT_PRODUCTS_DIR}/shared_preferences/shared_preferences.framework",
+ "${BUILT_PRODUCTS_DIR}/shared_preferences_ios/shared_preferences_ios.framework",
"${BUILT_PRODUCTS_DIR}/sqflite/sqflite.framework",
- "${BUILT_PRODUCTS_DIR}/url_launcher/url_launcher.framework",
- "${BUILT_PRODUCTS_DIR}/video_player/video_player.framework",
+ "${BUILT_PRODUCTS_DIR}/url_launcher_ios/url_launcher_ios.framework",
+ "${BUILT_PRODUCTS_DIR}/video_player_avfoundation/video_player_avfoundation.framework",
"${BUILT_PRODUCTS_DIR}/wakelock/wakelock.framework",
"${BUILT_PRODUCTS_DIR}/webview_flutter/webview_flutter.framework",
);
@@ -297,17 +297,17 @@
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/device_info.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/fluttertoast.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/image_gallery_saver.framework",
- "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/image_picker.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/image_picker_ios.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/nanopb.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/package_info.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/package_info_plus.framework",
- "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/path_provider.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/path_provider_ios.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/sentry_flutter.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/share.framework",
- "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/shared_preferences.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/shared_preferences_ios.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/sqflite.framework",
- "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/url_launcher.framework",
- "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/video_player.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/url_launcher_ios.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/video_player_avfoundation.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/wakelock.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/webview_flutter.framework",
);
@@ -429,7 +429,10 @@
);
INFOPLIST_FILE = Runner/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
@@ -565,7 +568,10 @@
);
INFOPLIST_FILE = Runner/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
@@ -597,7 +603,10 @@
);
INFOPLIST_FILE = Runner/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
index ad6250a..c87d15a 100644
--- a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
+++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
@@ -1,6 +1,6 @@
-
+
-
+
diff --git a/lib/SkinnedApp.dart b/lib/SkinnedApp.dart
index b1d3605..8f73260 100644
--- a/lib/SkinnedApp.dart
+++ b/lib/SkinnedApp.dart
@@ -1,6 +1,7 @@
import 'package:firebase_analytics/observer.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
+import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:fyx/FyxApp.dart';
import 'package:fyx/model/MainRepository.dart';
import 'package:fyx/pages/DiscussionPage.dart';
@@ -15,21 +16,30 @@ class SkinnedApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return CupertinoApp(
- title: 'Fyx',
- theme: Skin.of(context).theme.data,
- home: MainRepository().credentials != null && MainRepository().credentials!.isValid ? HomePage() : LoginPage(),
- debugShowCheckedModeBanner: FyxApp.isDev,
- onUnknownRoute: (RouteSettings settings) => CupertinoPageRoute(builder: (_) => DiscussionPage(), settings: settings),
- onGenerateRoute: FyxApp.routes,
- navigatorKey: FyxApp.navigatorKey,
- navigatorObservers: [
- FyxApp.routeObserver,
- FirebaseAnalyticsObserver(
- analytics: FyxApp.analytics,
- onError: (error) async => await Sentry.captureException(
- error,
- ))
- ],
- );
+ title: 'Fyx',
+ theme: Skin.of(context).theme.data,
+ home: MainRepository().credentials != null && MainRepository().credentials!.isValid ? HomePage() : LoginPage(),
+ debugShowCheckedModeBanner: FyxApp.isDev,
+ onUnknownRoute: (RouteSettings settings) => CupertinoPageRoute(builder: (_) => DiscussionPage(), settings: settings),
+ onGenerateRoute: FyxApp.routes,
+ navigatorKey: FyxApp.navigatorKey,
+ navigatorObservers: [
+ FyxApp.routeObserver,
+ FirebaseAnalyticsObserver(
+ analytics: FyxApp.analytics,
+ onError: (error) async => await Sentry.captureException(
+ error,
+ ))
+ ],
+ localizationsDelegates: [
+ GlobalMaterialLocalizations.delegate,
+ GlobalWidgetsLocalizations.delegate,
+ GlobalCupertinoLocalizations.delegate,
+ ],
+ supportedLocales: [
+ Locale('en', ''),
+ Locale('cs', ''),
+ Locale('sk', ''),
+ ]);
}
}
diff --git a/lib/components/ContentBoxLayout.dart b/lib/components/ContentBoxLayout.dart
index 4add767..1236c36 100644
--- a/lib/components/ContentBoxLayout.dart
+++ b/lib/components/ContentBoxLayout.dart
@@ -2,6 +2,7 @@ import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_html/shims/dart_ui.dart';
import 'package:fyx/components/post/Advertisement.dart';
+import 'package:fyx/components/post/Dice.dart';
import 'package:fyx/components/post/Poll.dart';
import 'package:fyx/components/post/PostFooterLink.dart';
import 'package:fyx/components/post/PostHeroAttachment.dart';
@@ -11,11 +12,12 @@ import 'package:fyx/model/enums/PostTypeEnum.dart';
import 'package:fyx/model/post/Content.dart';
import 'package:fyx/model/post/Image.dart' as model;
import 'package:fyx/model/post/content/Advertisement.dart';
+import 'package:fyx/model/post/content/Dice.dart';
import 'package:fyx/model/post/content/Poll.dart';
import 'package:fyx/theme/T.dart';
import 'package:fyx/theme/UnreadBadgeDecoration.dart';
-import 'package:fyx/theme/skin/SkinColors.dart';
import 'package:fyx/theme/skin/Skin.dart';
+import 'package:fyx/theme/skin/SkinColors.dart';
enum LAYOUT_TYPES { textOnly, oneImageOnly, attachmentsOnly, attachmentsAndText }
@@ -199,6 +201,8 @@ class ContentBoxLayout extends StatelessWidget {
switch (this.content.contentType) {
case PostTypeEnum.poll:
return Poll(content as ContentPoll);
+ case PostTypeEnum.dice:
+ return Dice(content as ContentDice);
case PostTypeEnum.text:
return PostHtml(content);
case PostTypeEnum.advertisement:
diff --git a/lib/components/PullToRefreshList.dart b/lib/components/PullToRefreshList.dart
index 44fff46..d7f2db7 100644
--- a/lib/components/PullToRefreshList.dart
+++ b/lib/components/PullToRefreshList.dart
@@ -236,14 +236,17 @@ class _PullToRefreshListState extends State {
}
}
- // Load the data only if there are any data AND should not be inactive.
- if (_result!.data.length > 0 && !makeInactive) {
+ // Load the data if should not be inactive.
+ if (!makeInactive) {
if (append) {
_slivers.removeLast(); // Remove the loading indicator
} else {
_slivers.removeRange(1, _slivers.length);
}
- _slivers.addAll(this.buildTheList(_result!.data));
+ // Render new data if anything actually arrived
+ if (_result!.data.length > 0) {
+ _slivers.addAll(this.buildTheList(_result!.data));
+ }
setState(() => _hasError = false);
setState(() => _lastId = _result!.lastId);
}
diff --git a/lib/components/post/Dice.dart b/lib/components/post/Dice.dart
new file mode 100644
index 0000000..0860ac8
--- /dev/null
+++ b/lib/components/post/Dice.dart
@@ -0,0 +1,126 @@
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/widgets.dart';
+import 'package:fyx/components/Avatar.dart';
+import 'package:fyx/controllers/ApiController.dart';
+import 'package:fyx/model/post/content/Dice.dart';
+import 'package:fyx/theme/Helpers.dart';
+import 'package:fyx/theme/T.dart';
+import 'package:fyx/theme/skin/Skin.dart';
+import 'package:fyx/theme/skin/SkinColors.dart';
+
+class Dice extends StatefulWidget {
+ final ContentDice content;
+
+ Dice(this.content);
+
+ @override
+ _DiceState createState() => _DiceState();
+}
+
+class _DiceState extends State {
+ bool _loading = false;
+ ContentDice? _dice;
+ ScrollController controller = ScrollController();
+
+ @override
+ void initState() {
+ _dice = widget.content;
+ super.initState();
+ }
+
+ Widget buildRolls(BuildContext context) {
+ SkinColors colors = Skin.of(context).theme.colors;
+
+ return ListView.builder(
+ physics: NeverScrollableScrollPhysics(),
+ controller: controller,
+ itemBuilder: (context, index) {
+ final roll = _dice!.rolls[index];
+ return Padding(
+ padding: const EdgeInsets.symmetric(vertical: 4.0),
+ child: Container(
+ padding: const EdgeInsets.all(8.0),
+ decoration: BoxDecoration(
+ color: colors.pollAnswer,
+ ),
+ child: Row(crossAxisAlignment: CrossAxisAlignment.start, children: [
+ Padding(
+ padding: const EdgeInsets.only(top: 8),
+ child: Text(
+ roll.rolls.reduce((a, b) => a + b).toString(),
+ style: TextStyle(fontSize: 14),
+ ),
+ ),
+ Tooltip(
+ message: '${roll.user}: ${roll.rolls.join(", ")}',
+ waitDuration: Duration(milliseconds: 0),
+ showDuration: Duration(milliseconds: 1500 + (roll.rolls.length * 300)),
+ child: Padding(
+ padding: const EdgeInsets.only(left: 5, bottom: 0),
+ child: Avatar(Helpers.avatarUrl(roll.user), size: 22, isHighlighted: false),
+ ),
+ )
+ ]),
+ ),
+ );
+ },
+ itemCount: _dice!.rolls.length,
+ shrinkWrap: true,
+ padding: const EdgeInsets.all(0));
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ SkinColors colors = Skin.of(context).theme.colors;
+
+ return Container(
+ alignment: Alignment.centerLeft,
+ child: Column(crossAxisAlignment: CrossAxisAlignment.stretch, children: [
+ Text(_dice!.reason, style: DefaultTextStyle.of(context).style.copyWith(fontSize: 20, fontWeight: FontWeight.bold)),
+ if (_dice!.showRollsAfter > 0 && _dice!.showRollsAfter > DateTime.now().millisecondsSinceEpoch)
+ Padding(
+ padding: EdgeInsets.only(top: 8),
+ child: Text(
+ 'Výsledky se zobrazí po ${Helpers.absoluteTime(_dice!.showRollsAfter)}',
+ style: TextStyle(fontStyle: FontStyle.italic),
+ )),
+ if (_dice!.allowRollsUntil > 0 && _dice!.allowRollsUntil > DateTime.now().millisecondsSinceEpoch)
+ Padding(
+ padding: EdgeInsets.only(top: 8),
+ child: Text(
+ 'Házet možné do ${Helpers.absoluteTime(_dice!.allowRollsUntil)}',
+ style: TextStyle(fontStyle: FontStyle.italic),
+ )),
+ SizedBox(
+ height: 8,
+ ),
+ buildRolls(context),
+ if (_dice!.canRoll)
+ Padding(
+ padding: const EdgeInsets.only(top: 16.0),
+ child: CupertinoButton(
+ onPressed: _loading
+ ? null
+ : () async {
+ setState(() => _loading = true);
+ try {
+ var poll = await ApiController().rollDice(_dice!.discussionId, _dice!.postId);
+ setState(() => _dice = poll);
+ } catch (error) {
+ T.error(error.toString(), bg: colors.danger);
+ } finally {
+ setState(() => _loading = false);
+ }
+ },
+ child: _loading ? CupertinoActivityIndicator() : Text('Hodit! ${_dice!.diceCount}d${_dice!.diceSides}'),
+ color: colors.primary,
+ padding: EdgeInsets.all(0),
+ disabledColor: colors.disabled,
+ ),
+ )
+ ]),
+ color: colors.pollBackground,
+ padding: EdgeInsets.all(15));
+ }
+}
diff --git a/lib/components/post/Poll.dart b/lib/components/post/Poll.dart
index 547b161..b674343 100644
--- a/lib/components/post/Poll.dart
+++ b/lib/components/post/Poll.dart
@@ -120,7 +120,7 @@ class _PollState extends State {
setState(() => _loading = false);
}
},
- child: _loading ? CupertinoActivityIndicator() : Text('Hlasovat ${_votes.length}/${_poll!.allowedVotes}'),
+ child: _loading ? CupertinoActivityIndicator() : Text('${_poll!.publicResults ? 'Veřejně hlasovat' : 'Hlasovat' } ${_votes.length}/${_poll!.allowedVotes}'),
color: colors.primary,
padding: EdgeInsets.all(0),
disabledColor: colors.disabled,
diff --git a/lib/components/post/PostHtml.dart b/lib/components/post/PostHtml.dart
index fd8ea56..ee64e92 100644
--- a/lib/components/post/PostHtml.dart
+++ b/lib/components/post/PostHtml.dart
@@ -133,11 +133,15 @@ class PostHtml extends StatelessWidget {
) {
final element = renderContext.tree.element;
- if (element!.attributes['style'] == 'background-color:#272822') {
+ if (element == null) {
+ return parsedChild;
+ }
+
+ if (element.attributes['style'] == 'background-color:#272822') {
final source = HtmlUnescape().convert(element.text);
return SyntaxHighlighter(source);
} else {
- return parsedChild;
+ return Text(element.text, style: TextStyle(fontFamily: 'JetBrainsMono'));
}
}
},
diff --git a/lib/components/post/PostListItem.dart b/lib/components/post/PostListItem.dart
index 3cc54fb..13d7295 100644
--- a/lib/components/post/PostListItem.dart
+++ b/lib/components/post/PostListItem.dart
@@ -8,11 +8,15 @@ import 'package:fyx/components/actionSheets/PostActionSheet.dart';
import 'package:fyx/components/actionSheets/PostAvatarActionSheet.dart';
import 'package:fyx/components/post/PostAvatar.dart';
import 'package:fyx/components/post/PostRating.dart';
+import 'package:fyx/components/post/PostThumbs.dart';
import 'package:fyx/controllers/AnalyticsProvider.dart';
import 'package:fyx/controllers/ApiController.dart';
import 'package:fyx/controllers/IApiProvider.dart';
import 'package:fyx/model/MainRepository.dart';
import 'package:fyx/model/Post.dart';
+import 'package:fyx/model/notifications/LoadRatingsNotification.dart';
+import 'package:fyx/model/post/PostThumbItem.dart';
+import 'package:fyx/model/reponses/PostRatingsResponse.dart';
import 'package:fyx/pages/NewMessagePage.dart';
import 'package:fyx/theme/Helpers.dart';
import 'package:fyx/theme/IconReply.dart';
@@ -40,6 +44,7 @@ class PostListItem extends StatefulWidget {
class _PostListItemState extends State {
Post? _post;
bool _isSaving = false;
+ bool _showRatings = false;
@override
void initState() {
@@ -83,9 +88,6 @@ class _PostListItemState extends State {
} else {
T.success('👍', bg: colors.success);
}
- print(response.currentRating);
- print(response.myRating);
- print(response.isGiven);
setState(() {
_post!.rating = response.currentRating;
_post!.myRating = response.myRating;
@@ -111,17 +113,9 @@ class _PostListItemState extends State {
descriptionWidget: Row(
children: [
if (_post!.rating != null)
- Container(
- padding: EdgeInsets.symmetric(horizontal: 8, vertical: 1),
- decoration: BoxDecoration(
- color: _post!.rating! > 0
- ? colors.success.withOpacity(Helpers.ratingRange(_post!.rating!))
- : (_post!.rating! < 0
- ? colors.danger.withOpacity(Helpers.ratingRange(_post!.rating!.abs()))
- : colors.text.withOpacity(0.2)),
- borderRadius: BorderRadius.circular(2)),
- child: Text(Post.formatRating(_post!.rating!), style: TextStyle(fontSize: 10)),
- ),
+ Text(Post.formatRating(_post!.rating!),
+ style:
+ TextStyle(fontSize: 10, color: _post!.rating! > 0 ? colors.success : (_post!.rating! < 0 ? colors.danger : colors.text))),
if (_post!.rating != null) SizedBox(width: 8),
Text(
Helpers.absoluteTime(_post!.time),
@@ -146,67 +140,137 @@ class _PostListItemState extends State {
postId: _post!.id,
shareData: ShareData(subject: '@${_post!.nick}', body: _post!.content, link: _post!.link),
flagPostCallback: (postId) => MainRepository().settings.blockPost(postId)))),
- bottomWidget: Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- children: [
- PostRating(_post!, onRatingChange: (post) => setState(() => _post = post)),
- Row(
- children: [
- Visibility(
- visible: widget._isPreview != true && _post!.canReply,
- child: GestureDetector(
- onTap: () => Navigator.of(context).pushNamed('/new-message',
- arguments: NewMessageSettings(
- replyWidget: PostListItem(
- _post!,
- isPreview: true,
- ),
- onClose: this.widget.onUpdate,
- onSubmit: (String? inputField, String message, List