Merge branch 'master' into feature/blocking-v2

This commit is contained in:
krawieck 2021-10-01 23:54:57 +02:00
commit 9ba800a435
91 changed files with 1572 additions and 728 deletions

View File

@ -24,6 +24,14 @@ A clear and concise description of what the bug is.
3. Scroll down to '....'
4. See error
### Relevant logs
<details>
<summary>Logs</summary>
Paste your logs here. Logs can be found in lemmur: settings > about lemmur > logs.
</details>
### Expected behavior
A clear and concise description of what you expected to happen.

View File

@ -7,16 +7,12 @@ on:
branches: [master]
jobs:
android:
name: Android
lint:
name: Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-java@v1
with:
java-version: "12.x"
- uses: subosito/flutter-action@v1
with:
channel: "stable"
@ -33,12 +29,51 @@ jobs:
- name: Run tests
run: flutter test
android:
name: Android
runs-on: ubuntu-latest
needs: lint
steps:
- uses: actions/checkout@v2
- uses: actions/setup-java@v1
with:
java-version: "12.x"
- uses: subosito/flutter-action@v1
with:
channel: "stable"
- name: Inject keystore
working-directory: android/app
run: |
echo "${{ secrets.SIGNING_KEY }}" | base64 -d | tee key.jks >/dev/null
- name: Android build
run: flutter build apk --split-per-abi
env:
ANDROID_KEY_ALIAS: ${{ secrets.ALIAS }}
ANDROID_KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
ANDROID_STORE_PATH: key.jks
ANDROID_STORE_PASSWORD: ${{ secrets.KEY_STORE_PASSWORD }}
run: flutter build apk --split-per-abi --release --target lib/main_prod.dart --flavor prod
ios:
name: iOS
runs-on: macos-latest
needs: lint
steps:
- uses: actions/checkout@v2
- uses: subosito/flutter-action@v1
with:
channel: "stable"
- run: flutter build ios --no-codesign --release --target lib/main_prod.dart --flavor prod
linux:
name: Linux
runs-on: ubuntu-latest
needs: lint
steps:
- uses: actions/checkout@v2
@ -57,11 +92,12 @@ jobs:
- name: Build
run: |
flutter build linux
flutter build linux --release --target lib/main_prod.dart
windows:
name: Windows
runs-on: windows-latest
needs: lint
steps:
- uses: actions/checkout@v2
@ -75,4 +111,4 @@ jobs:
- name: Build
run: |
flutter build windows
flutter build windows --release --target lib/main_prod.dart

View File

@ -37,36 +37,36 @@ jobs:
run: flutter pub get
- name: Inject keystore
working-directory: android
env:
KEY_STORE_PASSWORD: ${{ secrets.KEY_STORE_PASSWORD }}
KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
ALIAS: ${{ secrets.ALIAS }}
SIGNING_KEY: ${{ secrets.SIGNING_KEY }}
working-directory: android/app
run: |
echo storePassword=$KEY_STORE_PASSWORD > key.properties
echo keyPassword=$KEY_PASSWORD >> key.properties
echo keyAlias=$ALIAS >> key.properties
echo storeFile=$HOME/key.jks >> key.properties
echo $SIGNING_KEY | base64 -d | tee ~/key.jks >/dev/null
echo "${{ secrets.SIGNING_KEY }}" | base64 -d | tee key.jks >/dev/null
- name: Generate appbundle
run: flutter build appbundle
env:
ANDROID_KEY_ALIAS: ${{ secrets.ALIAS }}
ANDROID_KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
ANDROID_STORE_PATH: key.jks
ANDROID_STORE_PASSWORD: ${{ secrets.KEY_STORE_PASSWORD }}
run: flutter build appbundle --release --target lib/main_prod.dart --flavor prod
- uses: actions/upload-artifact@v2
with:
name: android-appbundle
path: |
build/app/outputs/bundle/release/app-release.aab
build/app/outputs/bundle/prodRelease/app-prod-release.aab
- name: Android build
run: |
flutter build apk --split-per-abi
env:
ANDROID_KEY_ALIAS: ${{ secrets.ALIAS }}
ANDROID_KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
ANDROID_STORE_PATH: key.jks
ANDROID_STORE_PASSWORD: ${{ secrets.KEY_STORE_PASSWORD }}
run:
flutter build apk --split-per-abi --release --target lib/main_prod.dart --flavor prod
mv build/app/outputs/flutter-apk/app-arm64-v8a-release.apk lemmur-${{ needs.get-vars.outputs.tag }}-arm64-v8a-android.apk
mv build/app/outputs/flutter-apk/app-armeabi-v7a-release.apk lemmur-${{ needs.get-vars.outputs.tag }}-armeabi-v7a-android.apk
mv build/app/outputs/flutter-apk/app-x86_64-release.apk lemmur-${{ needs.get-vars.outputs.tag }}-x86_64-android.apk
mv build/app/outputs/flutter-apk/app-arm64-v8a-prod-release.apk lemmur-${{ needs.get-vars.outputs.tag }}-arm64-v8a-android.apk
mv build/app/outputs/flutter-apk/app-armeabi-v7a-prod-release.apk lemmur-${{ needs.get-vars.outputs.tag }}-armeabi-v7a-android.apk
mv build/app/outputs/flutter-apk/app-x86_64-prod-release.apk lemmur-${{ needs.get-vars.outputs.tag }}-x86_64-android.apk
- uses: actions/upload-artifact@v2
with:
@ -96,17 +96,17 @@ jobs:
- name: Build
run: |
flutter build linux
flutter build linux --release --target lib/main_prod.dart
- name: Archive
working-directory: build/linux/release/bundle
working-directory: build/linux/x64/release/bundle
run: |
tar -czf lemmur-${{ needs.get-vars.outputs.tag }}-x86_64-linux.tar.gz *
- uses: actions/upload-artifact@v2
with:
name: linux-build
path: build/linux/release/bundle/lemmur-*.tar.gz
path: build/linux/x64/release/bundle/lemmur-*.tar.gz
windows-build:
name: Windows build
@ -125,7 +125,7 @@ jobs:
- name: Build
run: |
flutter build windows
flutter build windows --release --target lib/main_prod.dart
- name: Archive
working-directory: build/windows/runner/Release

3
.gitignore vendored
View File

@ -36,3 +36,6 @@ app.*.map.json
# Exceptions to above rules.
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
# Xcode build files
ios/build

12
.vscode/launch.json vendored
View File

@ -4,19 +4,25 @@
{
"name": "Debug",
"request": "launch",
"type": "dart"
"type": "dart",
"program": "lib/main_dev.dart",
"args": ["--flavor", "dev"]
},
{
"name": "Profile",
"request": "launch",
"type": "dart",
"flutterMode": "profile"
"flutterMode": "profile",
"program": "lib/main_dev.dart",
"args": ["--flavor", "dev"]
},
{
"name": "Release",
"request": "launch",
"type": "dart",
"flutterMode": "release"
"flutterMode": "release",
"program": "lib/main_dev.dart",
"args": ["--flavor", "dev"]
}
]
}

View File

@ -5,29 +5,50 @@
"body": ["\"$1\": \"$2\",", "\"@$1\": {}$0"]
},
"Assert not null": {
"scope": "dart",
"prefix": "assnotnull",
"body": ["assert($1 != null)$0"]
},
"sizedbox": {
"scope": "dart",
"prefix": "sizedbox",
"body": ["const SizedBox($1)$0"]
},
"theme": {
"scope": "dart",
"prefix": "theme",
"body": ["final theme = Theme.of(context);"]
},
"sleep": {
"scope": "dart",
"prefix": "sleep",
"body": [
"await Future<dynamic>.delayed(const Duration(milliseconds: ${1:1000}));$0"
]
},
"repeat widget": {
"scope": "dart",
"prefix": "repeat",
"body": ["for(int i = 0; i < $1; i++)$0"]
},
"L10n string": {
"scope": "dart",
"prefix": "l10n",
"body": ["L10n.of(context)!.$0"]
},
"Mobx store": {
"prefix": "mobxstore",
"body": [
"import 'package:mobx/mobx.dart';",
"",
"part '$TM_FILENAME_BASE.g.dart';",
"",
"class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/g} = _${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/g} with _$${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/g};",
"",
"abstract class _${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/g} with Store {",
"\t@observable",
"\t$0",
"}"
]
}
}

View File

@ -2,5 +2,6 @@
"files.associations": {
"*.arb": "json"
},
"dart.showTodos": false
"dart.showTodos": false,
"xml.format.preserveAttributeLineBreaks": true
}

View File

@ -1,3 +1,10 @@
## Unreleased
### Added
- Logging: local logs about some actions/errors. Can be accessed from **settings > about lemmur > logs**
- Android theme-aware splash screen (thanks to [@mimi89999](https://github.com/mimi89999))
## v0.6.0 - 2021-09-06
### Added

View File

@ -2,13 +2,13 @@ linter:
rules:
- avoid_bool_literals_in_conditional_expressions
- avoid_catching_errors
- avoid_classes_with_only_static_members
- avoid_equals_and_hash_code_on_mutable_classes
- avoid_escaping_inner_quotes
- avoid_function_literals_in_foreach_calls
- avoid_init_to_null
- avoid_null_checks_in_equality_operators
- avoid_positional_boolean_parameters
- avoid_print
- avoid_private_typedef_functions
- avoid_redundant_argument_values
- avoid_relative_lib_imports
@ -33,13 +33,16 @@ linter:
- directives_ordering
- empty_catches
- empty_constructor_bodies
- eol_at_end_of_file
- exhaustive_cases
- file_names
- hash_and_equals
- implementation_imports
- invariant_booleans
- library_names
- library_prefixes
- non_constant_identifier_names
- noop_primitive_operations
- null_check_on_nullable_type_parameter
- omit_local_variable_types
- one_member_abstracts
@ -102,6 +105,7 @@ linter:
- unrelated_type_equality_checks
- use_full_hex_values_for_flutter_colors
- use_is_even_rather_than_modulo
- use_test_throws_matchers
- use_raw_strings
- use_rethrow_when_possible
- use_setters_to_change_properties
@ -113,8 +117,6 @@ analyzer:
- "**/*.g.dart"
- "**/*.freezed.dart"
- "lib/gen/assets.gen.dart"
strong-mode:
# TODO: remove after migrating to null safety, this is already turned off by default
implicit-casts: false
# TODO: consider disabling
# implicit-dynamic: false
# strong-mode:
# TODO: consider disabling
# implicit-dynamic: false

View File

@ -25,12 +25,6 @@ apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file('key.properties')
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}
android {
compileSdkVersion 30
@ -51,21 +45,55 @@ android {
}
signingConfigs {
release {
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
storePassword keystoreProperties['storePassword']
dev { }
if (System.getenv("ANDROID_STORE_PATH")) {
prod {
keyAlias System.getenv("ANDROID_KEY_ALIAS")
keyPassword System.getenv("ANDROID_KEY_PASSWORD")
storeFile file(System.getenv("ANDROID_STORE_PATH"))
storePassword System.getenv("ANDROID_STORE_PASSWORD")
}
} else {
prod { }
}
}
}
flavorDimensions "app"
productFlavors {
dev {
dimension "app"
applicationIdSuffix ".dev"
versionNameSuffix "-dev"
manifestPlaceholders = [
appName: "lemmur DEV"
]
signingConfig signingConfigs.debug
}
prod {
dimension "app"
manifestPlaceholders = [
appName: "lemmur"
]
signingConfig signingConfigs.prod
}
}
buildTypes {
debug {
testCoverageEnabled true
debuggable true
minifyEnabled false
signingConfig null
}
release {
if (keystorePropertiesFile.exists()) {
signingConfig signingConfigs.release
} else {
signingConfig signingConfigs.debug
}
debuggable false
minifyEnabled true
shrinkResources false
zipAlignEnabled true
}
}
}

View File

@ -1,51 +1,38 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.krawieck.lemmur">
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
calls FlutterMain.startInitialization(this); in its onCreate method.
In most cases you can leave this as-is, but you if you want to provide
additional functionality it is fine to subclass or reimplement
FlutterApplication and put your custom class here. -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- Needed for url_launcher to work on android 11 -->
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.krawieck.lemmur">
<application
android:name="io.flutter.app.FlutterApplication"
android:label="lemmur"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<!-- Displays an Android View that continues showing the launch screen
Drawable until Flutter paints its first frame, then this splash
screen fades out. A splash screen is useful to avoid any visual
gap between the end of Android's launch screen and the painting of
Flutter's first frame. -->
<meta-data
android:name="io.flutter.embedding.android.SplashScreenDrawable"
android:resource="@drawable/launch_background"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
<uses-permission android:name="android.permission.INTERNET" />
<!-- Needed for url_launcher to work on android 11 -->
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
<application
android:name="io.flutter.app.FlutterApplication"
android:label="${appName}"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
</manifest>

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

View File

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/white" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/splash_screen_background_color" />
<item>
<bitmap
android:gravity="center"
android:src="@drawable/splash" />
</item>
</layer-list>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="splash_screen_background_color">#303030</color>
</resources>

View File

@ -1,18 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
Flutter draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>

View File

@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="ic_launcher_background">#ffffff</color>
</resources>
<color name="splash_screen_background_color">#fafafa</color>
</resources>

View File

@ -1,18 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting -->
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
Flutter draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
<item name="android:windowBackground">@drawable/splash_screen</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowBackground">@android:color/white</item>
<item name="android:windowBackground">@color/splash_screen_background_color</item>
</style>
</resources>

View File

@ -5,11 +5,11 @@ PODS:
- FMDB/standard (2.7.5)
- image_picker (0.0.1):
- Flutter
- package_info (0.0.1):
- package_info_plus (0.4.5):
- Flutter
- path_provider (0.0.1):
- Flutter
- share (0.0.1):
- share_plus (0.0.1):
- Flutter
- shared_preferences (0.0.1):
- Flutter
@ -22,9 +22,9 @@ PODS:
DEPENDENCIES:
- Flutter (from `Flutter`)
- image_picker (from `.symlinks/plugins/image_picker/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`)
- share (from `.symlinks/plugins/share/ios`)
- share_plus (from `.symlinks/plugins/share_plus/ios`)
- shared_preferences (from `.symlinks/plugins/shared_preferences/ios`)
- sqflite (from `.symlinks/plugins/sqflite/ios`)
- url_launcher (from `.symlinks/plugins/url_launcher/ios`)
@ -38,12 +38,12 @@ EXTERNAL SOURCES:
:path: Flutter
image_picker:
:path: ".symlinks/plugins/image_picker/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"
share:
:path: ".symlinks/plugins/share/ios"
share_plus:
:path: ".symlinks/plugins/share_plus/ios"
shared_preferences:
:path: ".symlinks/plugins/shared_preferences/ios"
sqflite:
@ -52,16 +52,16 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/url_launcher/ios"
SPEC CHECKSUMS:
Flutter: 434fef37c0980e73bb6479ef766c45957d4b510c
Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
image_picker: 50e7c7ff960e5f58faa4d1f4af84a771c671bc4a
package_info: 873975fc26034f0b863a300ad47e7f1ac6c7ec62
image_picker: e06f7a68f000bd36f552c1847e33cda96ed31f1f
package_info_plus: 6c92f08e1f853dc01228d6f553146438dafcd14e
path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c
share: 0b2c3e82132f5888bccca3351c504d0003b3b410
share_plus: 056a1e8ac890df3e33cb503afffaf1e9b4fbae68
shared_preferences: af6bfa751691cdc24be3045c43ec037377ada40d
sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904
url_launcher: 6fef411d543ceb26efce54b05a0a40bfd74cbbef
PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c
COCOAPODS: 1.10.1
COCOAPODS: 1.11.0

View File

@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 50;
objectVersion = 51;
objects = {
/* Begin PBXBuildFile section */
@ -33,10 +33,13 @@
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
20AF123CE6B282DF5FCC0E08 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
3064BA8287AEF7F9E6523E2E /* Pods-Runner.debug-prod.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug-prod.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug-prod.xcconfig"; sourceTree = "<group>"; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
4E5591CE3BD9F89AE791097F /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
5D359FC3B8BF643CBF087D7C /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
5DC9EF56CF79F18EC6F8E97B /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
5F74EE2F2B11182F6DF33F2E /* Pods-Runner.release-prod.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release-prod.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release-prod.xcconfig"; sourceTree = "<group>"; };
61F7B8503D323D03015ED0C2 /* Pods-Runner.profile-dev.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile-dev.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile-dev.xcconfig"; sourceTree = "<group>"; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
@ -47,6 +50,8 @@
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
BAF12CFD300959413D4373DD /* Pods-Runner.release-dev.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release-dev.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release-dev.xcconfig"; sourceTree = "<group>"; };
C282F331F7E23515AB5C91ED /* Pods-Runner.debug-dev.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug-dev.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug-dev.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -67,6 +72,11 @@
20AF123CE6B282DF5FCC0E08 /* Pods-Runner.debug.xcconfig */,
5D359FC3B8BF643CBF087D7C /* Pods-Runner.release.xcconfig */,
5DC9EF56CF79F18EC6F8E97B /* Pods-Runner.profile.xcconfig */,
C282F331F7E23515AB5C91ED /* Pods-Runner.debug-dev.xcconfig */,
3064BA8287AEF7F9E6523E2E /* Pods-Runner.debug-prod.xcconfig */,
BAF12CFD300959413D4373DD /* Pods-Runner.release-dev.xcconfig */,
5F74EE2F2B11182F6DF33F2E /* Pods-Runner.release-prod.xcconfig */,
61F7B8503D323D03015ED0C2 /* Pods-Runner.profile-dev.xcconfig */,
);
path = Pods;
sourceTree = "<group>";
@ -163,7 +173,7 @@
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 1020;
LastUpgradeCheck = 1250;
ORGANIZATIONNAME = "";
TargetAttributes = {
97C146ED1CF9000F007C117D = {
@ -306,87 +316,7 @@
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
249021D3217E4FDB00AE95B9 /* Profile */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Profile;
};
249021D4217E4FDB00AE95B9 /* Profile */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = NMDSW6KGG7;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
PRODUCT_BUNDLE_IDENTIFIER = com.krawieck.lemmur;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = Profile;
};
97C147031CF9000F007C117D /* Debug */ = {
1889477126E7F08600887334 /* Debug-prod */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
@ -433,15 +363,47 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
name = "Debug-prod";
};
97C147041CF9000F007C117D /* Release */ = {
1889477226E7F08600887334 /* Debug-prod */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
BUNDLE_NAME = lemmur;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = NMDSW6KGG7;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
PRODUCT_BUNDLE_IDENTIFIER = com.krawieck.lemmur;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = "Debug-prod";
};
1889477326E7F09600887334 /* Release-prod */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
@ -482,7 +444,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
@ -491,13 +453,14 @@
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Release;
name = "Release-prod";
};
97C147061CF9000F007C117D /* Debug */ = {
1889477426E7F09600887334 /* Release-prod */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
BUNDLE_NAME = lemmur;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = NMDSW6KGG7;
@ -518,17 +481,237 @@
PRODUCT_BUNDLE_IDENTIFIER = com.krawieck.lemmur;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = "Release-prod";
};
249021D3217E4FDB00AE95B9 /* Profile-dev */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = "Profile-dev";
};
249021D4217E4FDB00AE95B9 /* Profile-dev */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
BUNDLE_NAME = "lemmur DEV";
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = NMDSW6KGG7;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
PRODUCT_BUNDLE_IDENTIFIER = com.krawieck.lemmur.dev;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = "Profile-dev";
};
97C147031CF9000F007C117D /* Debug-dev */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = "Debug-dev";
};
97C147041CF9000F007C117D /* Release-dev */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = "Release-dev";
};
97C147061CF9000F007C117D /* Debug-dev */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
BUNDLE_NAME = "lemmur DEV";
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = NMDSW6KGG7;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
PRODUCT_BUNDLE_IDENTIFIER = com.krawieck.lemmur.dev;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = Debug;
name = "Debug-dev";
};
97C147071CF9000F007C117D /* Release */ = {
97C147071CF9000F007C117D /* Release-dev */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
BUNDLE_NAME = "lemmur DEV";
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = NMDSW6KGG7;
@ -546,13 +729,13 @@
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
PRODUCT_BUNDLE_IDENTIFIER = com.krawieck.lemmur;
PRODUCT_BUNDLE_IDENTIFIER = com.krawieck.lemmur.dev;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = Release;
name = "Release-dev";
};
/* End XCBuildConfiguration section */
@ -560,22 +743,26 @@
97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
isa = XCConfigurationList;
buildConfigurations = (
97C147031CF9000F007C117D /* Debug */,
97C147041CF9000F007C117D /* Release */,
249021D3217E4FDB00AE95B9 /* Profile */,
97C147031CF9000F007C117D /* Debug-dev */,
1889477126E7F08600887334 /* Debug-prod */,
97C147041CF9000F007C117D /* Release-dev */,
1889477326E7F09600887334 /* Release-prod */,
249021D3217E4FDB00AE95B9 /* Profile-dev */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
defaultConfigurationName = "Release-dev";
};
97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
isa = XCConfigurationList;
buildConfigurations = (
97C147061CF9000F007C117D /* Debug */,
97C147071CF9000F007C117D /* Release */,
249021D4217E4FDB00AE95B9 /* Profile */,
97C147061CF9000F007C117D /* Debug-dev */,
1889477226E7F08600887334 /* Debug-prod */,
97C147071CF9000F007C117D /* Release-dev */,
1889477426E7F09600887334 /* Release-prod */,
249021D4217E4FDB00AE95B9 /* Profile-dev */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
defaultConfigurationName = "Release-dev";
};
/* End XCConfigurationList section */
};

View File

@ -2,6 +2,6 @@
<Workspace
version = "1.0">
<FileRef
location = "group:Runner.xcodeproj">
location = "self:">
</FileRef>
</Workspace>

View File

@ -0,0 +1,78 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1250"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug-dev"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug-dev"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release-dev"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug-dev">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release-dev"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1020"
LastUpgradeVersion = "1250"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@ -23,7 +23,7 @@
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
buildConfiguration = "Debug-prod"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
@ -40,7 +40,7 @@
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
buildConfiguration = "Debug-prod"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
@ -61,7 +61,7 @@
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Profile"
buildConfiguration = "Release-prod"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
@ -78,10 +78,10 @@
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
buildConfiguration = "Debug-prod">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
buildConfiguration = "Release-prod"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -1,53 +1,55 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>lemmur</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>$(FLUTTER_BUILD_NAME)</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>$(FLUTTER_BUILD_NUMBER)</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(BUNDLE_NAME)</string>
<key>CFBundleDisplayName</key>
<string>$(BUNDLE_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>$(FLUTTER_BUILD_NAME)</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>$(FLUTTER_BUILD_NUMBER)</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<!-- Image picker -->
<key>NSPhotoLibraryUsageDescription</key>
<string>For uploading images for posts/avatars</string>
<key>NSCameraUsageDescription</key>
<string>For uploading images for posts/avatars</string>
<key>NSMicrophoneUsageDescription</key>
<string>For recording videos for posts</string>
</dict>
<!-- Image picker -->
<key>NSPhotoLibraryUsageDescription</key>
<string>For uploading images for posts/avatars</string>
<key>NSCameraUsageDescription</key>
<string>For uploading images for posts/avatars</string>
<key>NSMicrophoneUsageDescription</key>
<string>For recording videos for posts</string>
</dict>
</plist>

30
lib/app.dart Normal file
View File

@ -0,0 +1,30 @@
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:keyboard_dismisser/keyboard_dismisser.dart';
import 'hooks/stores.dart';
import 'l10n/l10n.dart';
import 'pages/home_page.dart';
import 'theme.dart';
class MyApp extends HookWidget {
const MyApp();
@override
Widget build(BuildContext context) {
final configStore = useConfigStore();
return KeyboardDismisser(
child: MaterialApp(
title: 'lemmur',
supportedLocales: L10n.supportedLocales,
localizationsDelegates: L10n.localizationsDelegates,
themeMode: configStore.theme,
darkTheme: configStore.amoledDarkMode ? amoledTheme : darkTheme,
locale: configStore.locale,
theme: lightTheme,
home: const HomePage(),
),
);
}
}

7
lib/app_config.dart Normal file
View File

@ -0,0 +1,7 @@
class AppConfig {
final bool debugMode;
const AppConfig({
required this.debugMode,
});
}

View File

@ -3,8 +3,6 @@ import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'ref.dart';
class Debounce {
final bool loading;
final VoidCallback callback;
@ -27,14 +25,14 @@ Debounce useDebounce(
final timerHandle = useRef<Timer?>(null);
cancel() {
timerHandle.current?.cancel();
timerHandle.value?.cancel();
loading.value = false;
}
useEffect(() => () => timerHandle.current?.cancel(), []);
useEffect(() => () => timerHandle.value?.cancel(), []);
start() {
timerHandle.current = Timer(delayDuration, () async {
timerHandle.value = Timer(delayDuration, () async {
loading.value = true;
await callback();
cancel();

View File

@ -3,8 +3,6 @@ import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'ref.dart';
class DelayedLoading {
final bool pending;
final bool loading;
@ -32,11 +30,11 @@ DelayedLoading useDelayedLoading(
loading: loading.value,
pending: pending.value,
start: () {
timerHandle.current = Timer(delayDuration, () => loading.value = true);
timerHandle.value = Timer(delayDuration, () => loading.value = true);
pending.value = true;
},
cancel: () {
timerHandle.current?.cancel();
timerHandle.value?.cancel();
pending.value = false;
loading.value = false;
},

View File

@ -3,7 +3,7 @@ import 'package:flutter_hooks/flutter_hooks.dart';
/// creates an [AsyncSnapshot] from the Future returned from the valueBuilder.
/// [keys] can be used to rebuild the Future
AsyncSnapshot<T?> useMemoFuture<T>(
AsyncSnapshot<T> useMemoFuture<T>(
Future<T> Function() valueBuilder, [
List<Object?> keys = const <Object>[],
]) =>

View File

@ -1,9 +0,0 @@
import 'package:flutter_hooks/flutter_hooks.dart';
class Ref<T> {
T current;
Ref(this.current);
}
/// see React's useRef
Ref<T> useRef<T>(T initialValue) => useMemoized(() => Ref(initialValue));

View File

@ -18,8 +18,10 @@ class Refreshable<T> {
///
/// `keys` will re-run the initial fetching thus yielding a
/// loading state in the AsyncSnapshot
Refreshable<T?> useRefreshable<T>(AsyncValueGetter<T> fetcher,
[List<Object> keys = const <Object>[]]) {
Refreshable<T> useRefreshable<T extends Object>(
AsyncValueGetter<T> fetcher, [
List<Object> keys = const <Object>[],
]) {
final newData = useState<T?>(null);
final snapshot = useMemoFuture(() async {
newData.value = null;
@ -28,7 +30,7 @@ Refreshable<T?> useRefreshable<T>(AsyncValueGetter<T> fetcher,
final outSnapshot = () {
if (newData.value != null) {
return AsyncSnapshot.withData(ConnectionState.done, newData.value);
return AsyncSnapshot.withData(ConnectionState.done, newData.value!);
}
return snapshot;
}();

57
lib/main_common.dart Normal file
View File

@ -0,0 +1,57 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:logging/logging.dart';
import 'package:provider/provider.dart';
import 'app.dart';
import 'app_config.dart';
import 'pages/log_console_page/log_console_page_store.dart';
import 'stores/accounts_store.dart';
import 'stores/config_store.dart';
Future<void> mainCommon(AppConfig appConfig) async {
WidgetsFlutterBinding.ensureInitialized();
final logConsoleStore = LogConsolePageStore();
_setupLogger(appConfig, logConsoleStore);
final configStore = await ConfigStore.load();
final accountsStore = await AccountsStore.load();
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider.value(value: configStore),
ChangeNotifierProvider.value(value: accountsStore),
Provider.value(value: logConsoleStore),
],
child: const MyApp(),
),
);
}
void _setupLogger(AppConfig appConfig, LogConsolePageStore logConsoleStore) {
Logger.root.level = Level.ALL;
Logger.root.onRecord.listen((logRecord) {
// ignore: avoid_print
print(logRecord);
logConsoleStore.addLog(logRecord);
});
final flutterErrorLogger = Logger('FlutterError');
FlutterError.onError = (details) {
if (appConfig.debugMode) {
FlutterError.dumpErrorToConsole(details);
} else {
flutterErrorLogger.warning(
details.summary.name,
details.exception,
details.stack,
);
}
};
}

6
lib/main_dev.dart Normal file
View File

@ -0,0 +1,6 @@
import 'app_config.dart';
import 'main_common.dart';
void main() {
mainCommon(const AppConfig(debugMode: true));
}

6
lib/main_prod.dart Normal file
View File

@ -0,0 +1,6 @@
import 'app_config.dart';
import 'main_common.dart';
void main() {
mainCommon(const AppConfig(debugMode: false));
}

View File

@ -271,8 +271,8 @@ class _CommunitySubscribeToggle extends HookWidget {
decoration: delayed.loading
? null
: BoxDecoration(
color: subbed.value ? theme.accentColor : null,
border: Border.all(color: theme.accentColor),
color: subbed.value ? theme.colorScheme.secondary : null,
border: Border.all(color: theme.colorScheme.secondary),
borderRadius: BorderRadius.circular(7),
),
child: delayed.loading
@ -281,8 +281,8 @@ class _CommunitySubscribeToggle extends HookWidget {
: Icon(
subbed.value ? Icons.done : Icons.add,
color: subbed.value
? textColorBasedOnBackground(theme.accentColor)
: theme.accentColor,
? textColorBasedOnBackground(theme.colorScheme.secondary)
: theme.colorScheme.secondary,
size: 20,
),
),

View File

@ -381,8 +381,10 @@ class _AboutTab extends StatelessWidget {
if (community.community.description != null) ...[
Padding(
padding: const EdgeInsets.symmetric(horizontal: 15),
child: MarkdownText(community.community.description!,
instanceHost: community.instanceHost),
child: MarkdownText(
community.community.description!,
instanceHost: community.instanceHost,
),
),
const _Divider(),
],

View File

@ -1,4 +1,3 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:image_picker/image_picker.dart';
@ -33,11 +32,10 @@ class CreatePostFab extends HookWidget {
return FloatingActionButton(
onPressed: loggedInAction((_) async {
final postView = await showCupertinoModalPopup<PostView>(
context: context,
builder: (_) => community == null
? const CreatePostPage()
: CreatePostPage.toCommunity(community!),
final postView = await Navigator.of(context).push(
community == null
? CreatePostPage.route()
: CreatePostPage.toCommunityRoute(community!),
);
if (postView != null) {
@ -67,7 +65,7 @@ class CreatePostPage extends HookWidget {
const CreatePostPage.toCommunity(CommunityView this.community)
: _isEdit = false,
post = null;
const CreatePostPage.edit(this.post)
const CreatePostPage.edit(Post this.post)
: _isEdit = true,
community = null;
@ -114,7 +112,7 @@ class CreatePostPage extends HookWidget {
uploadPicture(Jwt token) async {
try {
final pic = await imagePicker.getImage(source: ImageSource.gallery);
final pic = await imagePicker.pickImage(source: ImageSource.gallery);
// pic is null when the picker was cancelled
if (pic != null) {
imageUploadLoading.value = true;
@ -352,4 +350,20 @@ class CreatePostPage extends HookWidget {
),
);
}
static Route<PostView> route() => MaterialPageRoute(
builder: (context) => const CreatePostPage(),
fullscreenDialog: true,
);
static Route<PostView> toCommunityRoute(CommunityView community) =>
MaterialPageRoute(
builder: (context) => CreatePostPage.toCommunity(community),
fullscreenDialog: true,
);
static Route<PostView> editRoute(Post post) => MaterialPageRoute(
builder: (context) => CreatePostPage.edit(post),
fullscreenDialog: true,
);
}

View File

@ -123,8 +123,7 @@ class CommentSection extends StatelessWidget {
com,
key: ValueKey(com),
),
const BottomSafe(
kMinInteractiveDimension + kFloatingActionButtonMargin),
const BottomSafe.fab(),
]
],
);

View File

@ -14,7 +14,6 @@ import '../../util/extensions/api.dart';
import '../../util/icons.dart';
import '../../util/observer_consumers.dart';
import '../../util/share.dart';
import '../../util/unawaited.dart';
import '../../widgets/post/post.dart';
import '../../widgets/post/post_more_menu.dart';
import '../../widgets/post/post_store.dart';
@ -119,9 +118,8 @@ class _FullPostPage extends HookWidget {
sharePost() => share(post.post.apId, context: context);
comment() async {
final newComment = await showCupertinoModalPopup<CommentView>(
context: context,
builder: (_) => WriteComment.toPost(post.post),
final newComment = await Navigator.of(context).push(
WriteComment.toPostRoute(post.post),
);
if (newComment != null) {

View File

@ -1,64 +1,16 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:keyboard_dismisser/keyboard_dismisser.dart';
import 'package:provider/provider.dart';
import 'hooks/stores.dart';
import 'l10n/l10n.dart';
import 'pages/communities_tab.dart';
import 'pages/create_post.dart';
import 'pages/home_tab.dart';
import 'pages/profile_tab.dart';
import 'pages/search_tab.dart';
import 'stores/accounts_store.dart';
import 'stores/config_store.dart';
import 'theme.dart';
import 'util/extensions/brightness.dart';
import '../util/extensions/brightness.dart';
import 'communities_tab.dart';
import 'create_post.dart';
import 'home_tab.dart';
import 'profile_tab.dart';
import 'search_tab.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
final configStore = await ConfigStore.load();
final accountsStore = await AccountsStore.load();
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider.value(value: configStore),
ChangeNotifierProvider.value(value: accountsStore),
],
child: const MyApp(),
),
);
}
class MyApp extends HookWidget {
const MyApp();
@override
Widget build(BuildContext context) {
final configStore = useConfigStore();
return KeyboardDismisser(
child: MaterialApp(
title: 'lemmur',
supportedLocales: L10n.supportedLocales,
localizationsDelegates: L10n.localizationsDelegates,
themeMode: configStore.theme,
darkTheme: configStore.amoledDarkMode ? amoledTheme : darkTheme,
locale: configStore.locale,
theme: lightTheme,
home: const MyHomePage(),
),
);
}
}
class MyHomePage extends HookWidget {
const MyHomePage();
class HomePage extends HookWidget {
const HomePage();
static const List<Widget> pages = [
HomeTab(),
@ -90,7 +42,7 @@ class MyHomePage extends HookWidget {
return IconButton(
icon: Icon(icon),
color: tabNum == currentTab.value ? theme.accentColor : null,
color: tabNum == currentTab.value ? theme.colorScheme.secondary : null,
onPressed: () => currentTab.value = tabNum,
);
}

View File

@ -1,7 +1,6 @@
import 'dart:math' show max;
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:lemmy_api_client/v3.dart';
@ -158,10 +157,8 @@ class HomeTab extends HookWidget {
: null),
),
onTap: accStore.isAnonymousFor(instance)
? () => showCupertinoModalPopup(
context: context,
builder: (_) =>
AddAccountPage(instanceHost: instance))
? () => Navigator.of(context)
.push(AddAccountPage.route(instance))
: () => pop(_SelectedList(
listingType: PostListingType.subscribed,
instanceHost: instance,
@ -236,7 +233,7 @@ class HomeTab extends HookWidget {
Flexible(
child: Text(
title,
style: theme.appBarTheme.textTheme?.headline6,
style: theme.appBarTheme.titleTextStyle,
overflow: TextOverflow.fade,
softWrap: false,
),

View File

@ -1,7 +1,6 @@
import 'dart:math' show pi;
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:lemmy_api_client/v3.dart';
@ -75,7 +74,7 @@ class InboxPage extends HookWidget {
Flexible(
child: Text(
displayString,
style: theme.appBarTheme.textTheme?.headline6,
style: theme.appBarTheme.titleTextStyle,
overflow: TextOverflow.fade,
softWrap: false,
),
@ -313,7 +312,7 @@ class PrivateMessageTile extends HookWidget {
),
Text(
otherSide.originPreferredName,
style: TextStyle(color: theme.accentColor),
style: TextStyle(color: theme.colorScheme.secondary),
),
],
),
@ -354,7 +353,7 @@ class PrivateMessageTile extends HookWidget {
),
if (toMe) ...[
TileAction(
iconColor: read.value ? theme.accentColor : null,
iconColor: read.value ? theme.colorScheme.secondary : null,
icon: Icons.check,
tooltip: L10n.of(context)!.mark_as_read,
onPressed: handleRead,
@ -364,12 +363,12 @@ class PrivateMessageTile extends HookWidget {
icon: Icons.reply,
tooltip: L10n.of(context)!.reply,
onPressed: () {
showCupertinoModalPopup(
context: context,
builder: (_) => WriteMessagePage.send(
instanceHost: pmv.value.instanceHost,
recipient: otherSide,
));
Navigator.of(context).push(
WriteMessagePage.sendRoute(
instanceHost: pmv.value.instanceHost,
recipient: otherSide,
),
);
},
)
] else ...[
@ -377,9 +376,8 @@ class PrivateMessageTile extends HookWidget {
icon: Icons.edit,
tooltip: L10n.of(context)!.edit,
onPressed: () async {
final val = await showCupertinoModalPopup<PrivateMessageView>(
context: context,
builder: (_) => WriteMessagePage.edit(pmv.value));
final val = await Navigator.of(context)
.push(WriteMessagePage.editRoute(pmv.value));
if (val != null) pmv.value = val;
},
),

View File

@ -1,5 +1,4 @@
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:lemmy_api_client/v3.dart';
@ -38,7 +37,7 @@ class InstancePage extends HookWidget {
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final siteSnap = useFuture(siteFuture, initialData: null);
final siteSnap = useFuture(siteFuture);
final colorOnCard = textColorBasedOnBackground(theme.cardColor);
final accStore = useAccountsStore();
final scrollController = useScrollController();
@ -233,7 +232,7 @@ class _AboutTab extends HookWidget {
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final commSnap = useFuture(communitiesFuture, initialData: null);
final commSnap = useFuture(communitiesFuture);
final accStore = useAccountsStore();
void goToCommunities() {

View File

@ -0,0 +1,81 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:logging/logging.dart';
import 'package:provider/provider.dart';
import '../../util/observer_consumers.dart';
import '../../widgets/bottom_safe.dart';
import 'log_console_page_store.dart';
class LogConsolePage extends StatelessWidget {
const LogConsolePage();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Logs')),
body: SafeArea(
child: ObserverBuilder<LogConsolePageStore>(
builder: (context, store) {
final logStrings = store.stringified();
if (store.logs.isEmpty) {
return const Center(
child: Text(
'no logs',
style: TextStyle(fontStyle: FontStyle.italic),
),
);
}
return ListView.separated(
padding: const EdgeInsets.all(8)
.copyWith(bottom: BottomSafe.fabPadding + 8),
itemCount: store.logs.length,
itemBuilder: (context, i) => SelectableText(
logStrings[i],
style: TextStyle(color: store.logs[i].level.color),
),
separatorBuilder: (context, i) => const SizedBox(height: 6),
);
},
),
),
floatingActionButton: FloatingActionButton(
onPressed: () async {
final data = context.read<LogConsolePageStore>().stringified();
await Clipboard.setData(ClipboardData(text: data.join('\n')));
ScaffoldMessenger.of(context)
..hideCurrentSnackBar()
..showSnackBar(
const SnackBar(content: Text('all logs copied to the clipboard')),
);
},
tooltip: 'Copy to clipboard',
child: const Icon(Icons.copy),
),
);
}
static Route route() => MaterialPageRoute(
builder: (context) => const LogConsolePage(),
fullscreenDialog: true,
);
}
extension on Level {
Color get color {
if (this == Level.FINEST) return Colors.lime[100]!;
if (this == Level.FINER) return Colors.lime[300]!;
if (this == Level.FINE) return Colors.lime;
if (this == Level.CONFIG) return Colors.green;
if (this == Level.INFO) return Colors.blue;
if (this == Level.WARNING) return Colors.amber;
if (this == Level.SEVERE) return Colors.orange;
if (this == Level.SHOUT) return Colors.red;
throw StateError('unreachable');
}
}

View File

@ -0,0 +1,33 @@
import 'package:logging/logging.dart';
import 'package:mobx/mobx.dart';
part 'log_console_page_store.g.dart';
class LogConsolePageStore = _LogConsolePageStore with _$LogConsolePageStore;
abstract class _LogConsolePageStore with Store {
// TODO: implement as an ObservableDeque
final logs = ObservableList<LogRecord>();
static const _bufferSize = 200;
@action
void addLog(LogRecord logRecord) {
if (logs.length == _bufferSize) {
logs.removeAt(0);
}
logs.add(logRecord);
}
List<String> stringified() {
return logs.map(
(log) {
var str = '${log.time} $log';
if (log.stackTrace != null) str += '\n${log.stackTrace}';
return str;
},
).toList();
}
}

View File

@ -0,0 +1,32 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'log_console_page_store.dart';
// **************************************************************************
// StoreGenerator
// **************************************************************************
// ignore_for_file: non_constant_identifier_names, unnecessary_brace_in_string_interps, unnecessary_lambdas, prefer_expression_function_bodies, lines_longer_than_80_chars, avoid_as, avoid_annotating_with_dynamic
mixin _$LogConsolePageStore on _LogConsolePageStore, Store {
final _$_LogConsolePageStoreActionController =
ActionController(name: '_LogConsolePageStore');
@override
void addLog(LogRecord logRecord) {
final _$actionInfo = _$_LogConsolePageStoreActionController.startAction(
name: '_LogConsolePageStore.addLog');
try {
return super.addLog(logRecord);
} finally {
_$_LogConsolePageStoreActionController.endAction(_$actionInfo);
}
}
@override
String toString() {
return '''
''';
}
}

View File

@ -0,0 +1,32 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'log_console_store.dart';
// **************************************************************************
// StoreGenerator
// **************************************************************************
// ignore_for_file: non_constant_identifier_names, unnecessary_brace_in_string_interps, unnecessary_lambdas, prefer_expression_function_bodies, lines_longer_than_80_chars, avoid_as, avoid_annotating_with_dynamic
mixin _$LogConsoleStore on _LogConsoleStore, Store {
final _$_LogConsoleStoreActionController =
ActionController(name: '_LogConsoleStore');
@override
void addLog(LogRecord logRecord) {
final _$actionInfo = _$_LogConsoleStoreActionController.startAction(
name: '_LogConsoleStore.addLog');
try {
return super.addLog(logRecord);
} finally {
_$_LogConsoleStoreActionController.endAction(_$actionInfo);
}
}
@override
String toString() {
return '''
''';
}
}

View File

@ -8,7 +8,6 @@ import 'package:url_launcher/url_launcher.dart' as ul;
import '../hooks/delayed_loading.dart';
import '../hooks/image_picker.dart';
import '../hooks/ref.dart';
import '../hooks/stores.dart';
import '../l10n/l10n.dart';
import '../util/icons.dart';
@ -151,8 +150,8 @@ class _ManageAccount extends HookWidget {
showReadPosts: showReadPosts.value,
sendNotificationsToEmail: sendNotificationsToEmail.value,
auth: token.raw,
avatar: avatar.current,
banner: banner.current,
avatar: avatar.value,
banner: banner.value,
matrixUserId: matrixUserController.text.isEmpty
? null
: matrixUserController.text,
@ -163,8 +162,8 @@ class _ManageAccount extends HookWidget {
email: emailController.text.isEmpty ? null : emailController.text,
));
informAcceptedAvatarRef.current?.call();
informAcceptedBannerRef.current?.call();
informAcceptedAvatarRef.value?.call();
informAcceptedBannerRef.value?.call();
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
content: Text('User settings saved'),
@ -243,16 +242,16 @@ class _ManageAccount extends HookWidget {
_ImagePicker(
user: user,
name: L10n.of(context)!.avatar,
initialUrl: avatar.current,
onChange: (value) => avatar.current = value,
initialUrl: avatar.value,
onChange: (value) => avatar.value = value,
informAcceptedRef: informAcceptedAvatarRef,
),
const SizedBox(height: 8),
_ImagePicker(
user: user,
name: L10n.of(context)!.banner,
initialUrl: banner.current,
onChange: (value) => banner.current = value,
initialUrl: banner.value,
onChange: (value) => banner.value = value,
informAcceptedRef: informAcceptedBannerRef,
),
const SizedBox(height: 8),
@ -396,7 +395,7 @@ class _ImagePicker extends HookWidget {
/// _ImagePicker will set the ref to a callback that can inform _ImagePicker
/// that the current picture is accepted
/// and should no longer allow for deletion of it
final Ref<VoidCallback?> informAcceptedRef;
final ObjectRef<VoidCallback?> informAcceptedRef;
const _ImagePicker({
Key? key,
@ -413,7 +412,7 @@ class _ImagePicker extends HookWidget {
// basically saves the very first initialUrl
final initialUrl = useRef(this.initialUrl);
final theme = Theme.of(context);
final url = useState(initialUrl.current);
final url = useState(initialUrl.value);
final pictrsDeleteToken = useState<PictrsUploadFile?>(null);
final imagePicker = useImagePicker();
@ -422,7 +421,7 @@ class _ImagePicker extends HookWidget {
uploadImage() async {
try {
final pic = await imagePicker.getImage(source: ImageSource.gallery);
final pic = await imagePicker.pickImage(source: ImageSource.gallery);
// pic is null when the picker was cancelled
if (pic != null) {
delayedLoading.start();
@ -456,15 +455,15 @@ class _ImagePicker extends HookWidget {
if (updateState) {
pictrsDeleteToken.value = null;
url.value = initialUrl.current;
url.value = initialUrl.value;
onChange?.call(url.value);
}
}
useEffect(() {
informAcceptedRef.current = () {
informAcceptedRef.value = () {
pictrsDeleteToken.value = null;
initialUrl.current = url.value;
initialUrl.value = url.value;
};
return () {

View File

@ -2,6 +2,7 @@ import 'dart:math' show max, min;
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:matrix4_transform/matrix4_transform.dart';
import 'package:photo_view/photo_view.dart';
@ -69,7 +70,7 @@ class MediaViewPage extends HookWidget {
Colors.black.withOpacity(max(0, 1.0 - (offset.value.dy.abs() / 200))),
appBar: showButtons.value
? AppBar(
brightness: Brightness.dark,
systemOverlayStyle: SystemUiOverlayStyle.light,
iconTheme: const IconThemeData(color: Colors.white),
backgroundColor: Colors.black38,
leading: const CloseButton(),

View File

@ -133,7 +133,7 @@ class _ModlogTable extends StatelessWidget {
),
TextSpan(
text: ' ${user.preferredName}',
style: TextStyle(color: theme.accentColor),
style: TextStyle(color: theme.colorScheme.secondary),
recognizer: TapGestureRecognizer()
..onTap = () => goToUser.byId(
context,
@ -155,7 +155,7 @@ class _ModlogTable extends StatelessWidget {
),
TextSpan(
text: ' !${community.name}',
style: TextStyle(color: theme.accentColor),
style: TextStyle(color: theme.colorScheme.secondary),
recognizer: TapGestureRecognizer()
..onTap = () => goToCommunity.byId(
context,
@ -180,7 +180,7 @@ class _ModlogTable extends StatelessWidget {
const TextSpan(text: ' post '),
TextSpan(
text: '"${removedPost.post.name}"',
style: TextStyle(color: theme.accentColor),
style: TextStyle(color: theme.colorScheme.secondary),
recognizer: TapGestureRecognizer()
..onTap = () => goToPost(
context,
@ -206,7 +206,7 @@ class _ModlogTable extends StatelessWidget {
const TextSpan(text: ' post '),
TextSpan(
text: '"${lockedPost.post.name}"',
style: TextStyle(color: theme.accentColor),
style: TextStyle(color: theme.colorScheme.secondary),
recognizer: TapGestureRecognizer()
..onTap = () => goToPost(
context,
@ -232,7 +232,7 @@ class _ModlogTable extends StatelessWidget {
const TextSpan(text: ' post '),
TextSpan(
text: '"${stickiedPost.post.name}"',
style: TextStyle(color: theme.accentColor),
style: TextStyle(color: theme.colorScheme.secondary),
recognizer: TapGestureRecognizer()
..onTap = () => goToPost(
context,
@ -259,7 +259,7 @@ class _ModlogTable extends StatelessWidget {
TextSpan(
text:
'"${removedComment.comment.content.replaceAll('\n', ' ')}"',
style: TextStyle(color: theme.accentColor),
style: TextStyle(color: theme.colorScheme.secondary),
recognizer: TapGestureRecognizer()
..onTap = () => goToPost(
context,
@ -553,7 +553,8 @@ class _ModlogEntry {
),
Text(
' ${mod.preferredName}',
style: TextStyle(color: Theme.of(context).accentColor),
style:
TextStyle(color: Theme.of(context).colorScheme.secondary),
),
],
),

View File

@ -1,4 +1,3 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
@ -80,7 +79,7 @@ class UserProfileTab extends HookWidget {
Text(
// TODO: fix overflow issues
displayValue,
style: theme.appBarTheme.textTheme?.headline6,
style: theme.appBarTheme.titleTextStyle,
overflow: TextOverflow.fade,
),
const Icon(Icons.expand_more),

View File

@ -1,5 +1,4 @@
import 'package:collection/collection.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';

View File

@ -1,5 +1,4 @@
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:lemmy_api_client/v3.dart';
@ -123,10 +122,8 @@ class AddAccountPage extends HookWidget {
),
title: const Text('Add instance'),
onTap: () async {
final value = await showCupertinoModalPopup<String>(
context: context,
builder: (context) => const AddInstancePage(),
);
final value =
await Navigator.of(context).push(AddInstancePage.route());
Navigator.of(context).pop(value);
},
),
@ -178,4 +175,9 @@ class AddAccountPage extends HookWidget {
),
);
}
static Route<String> route(String instanceHost) => MaterialPageRoute(
builder: (context) => AddAccountPage(instanceHost: instanceHost),
fullscreenDialog: true,
);
}

View File

@ -132,4 +132,9 @@ class AddInstancePage extends HookWidget {
),
);
}
static Route<String> route() => MaterialPageRoute(
builder: (context) => const AddInstancePage(),
fullscreenDialog: true,
);
}

View File

@ -1,4 +1,3 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
@ -326,7 +325,6 @@ class AccountsConfigPage extends HookWidget {
);
}
// TODO: speeddial v3 has really stupid defaults here https://github.com/darioielardi/flutter_speed_dial/issues/149
return Scaffold(
key: _scaffoldKey,
appBar: AppBar(
@ -336,23 +334,17 @@ class AccountsConfigPage extends HookWidget {
animatedIcon: AnimatedIcons.menu_close, // TODO: change to + => x
curve: Curves.bounceIn,
tooltip: 'Add account or instance',
overlayColor: theme.canvasColor,
children: [
SpeedDialChild(
child: const Icon(Icons.person_add),
label: 'Add account',
labelBackgroundColor: theme.canvasColor,
onTap: () => showCupertinoModalPopup(
context: context,
builder: (_) =>
AddAccountPage(instanceHost: accountsStore.instances.last)),
onTap: () => Navigator.of(context)
.push(AddAccountPage.route(accountsStore.instances.last)),
),
SpeedDialChild(
child: const Icon(Icons.dns),
labelBackgroundColor: theme.canvasColor,
label: 'Add instance',
onTap: () => showCupertinoModalPopup(
context: context, builder: (_) => const AddInstancePage()),
onTap: () => Navigator.of(context).push(AddInstancePage.route()),
),
],
child: const Icon(Icons.add),
@ -366,10 +358,8 @@ class AccountsConfigPage extends HookWidget {
Padding(
padding: const EdgeInsets.only(top: 100),
child: TextButton.icon(
onPressed: () => showCupertinoModalPopup(
context: context,
builder: (_) => const AddInstancePage(),
),
onPressed: () =>
Navigator.of(context).push(AddInstancePage.route()),
icon: const Icon(Icons.add),
label: const Text('Add instance'),
),
@ -409,9 +399,7 @@ class AccountsConfigPage extends HookWidget {
leading: const Icon(Icons.add),
title: const Text('Add account'),
onTap: () {
showCupertinoModalPopup(
context: context,
builder: (_) => AddAccountPage(instanceHost: instance));
Navigator.of(context).push(AddAccountPage.route(instance));
},
),
]

View File

@ -1,4 +1,3 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:lemmy_api_client/v3.dart';
@ -25,7 +24,7 @@ class UserPage extends HookWidget {
@override
Widget build(BuildContext context) {
final userDetailsSnap = useFuture(_userDetails, initialData: null);
final userDetailsSnap = useFuture(_userDetails);
final body = () {
if (userDetailsSnap.hasData) {
@ -69,12 +68,14 @@ class SendMessageButton extends HookWidget {
return IconButton(
icon: const Icon(Icons.email),
onPressed: loggedInAction((token) => showCupertinoModalPopup(
context: context,
builder: (_) => WriteMessagePage.send(
instanceHost: user.instanceHost,
recipient: user,
))),
onPressed: loggedInAction(
(token) => Navigator.of(context).push(
WriteMessagePage.sendRoute(
instanceHost: user.instanceHost,
recipient: user,
),
),
),
);
}
}

View File

@ -133,4 +133,22 @@ class WriteMessagePage extends HookWidget {
),
);
}
static Route<PrivateMessageView> sendRoute({
required PersonSafe recipient,
required String instanceHost,
}) =>
MaterialPageRoute(
builder: (context) => WriteMessagePage.send(
recipient: recipient,
instanceHost: instanceHost,
),
fullscreenDialog: true,
);
static Route<PrivateMessageView> editRoute(PrivateMessageView pmv) =>
MaterialPageRoute(
builder: (context) => WriteMessagePage.edit(pmv),
fullscreenDialog: true,
);
}

View File

@ -6,23 +6,23 @@ part of 'accounts_store.dart';
// JsonSerializableGenerator
// **************************************************************************
AccountsStore _$AccountsStoreFromJson(Map<String, dynamic> json) {
return AccountsStore()
..accounts = (json['accounts'] as Map<String, dynamic>?)?.map(
(k, e) => MapEntry(
k,
(e as Map<String, dynamic>).map(
(k, e) =>
MapEntry(k, UserData.fromJson(e as Map<String, dynamic>)),
)),
) ??
{'lemmy.ml': {}}
..defaultAccounts = (json['defaultAccounts'] as Map<String, dynamic>?)?.map(
(k, e) => MapEntry(k, e as String),
) ??
{}
..defaultAccount = json['defaultAccount'] as String?;
}
AccountsStore _$AccountsStoreFromJson(Map<String, dynamic> json) =>
AccountsStore()
..accounts = (json['accounts'] as Map<String, dynamic>?)?.map(
(k, e) => MapEntry(
k,
(e as Map<String, dynamic>).map(
(k, e) =>
MapEntry(k, UserData.fromJson(e as Map<String, dynamic>)),
)),
) ??
{'lemmy.ml': {}}
..defaultAccounts =
(json['defaultAccounts'] as Map<String, dynamic>?)?.map(
(k, e) => MapEntry(k, e as String),
) ??
{}
..defaultAccount = json['defaultAccount'] as String?;
Map<String, dynamic> _$AccountsStoreToJson(AccountsStore instance) =>
<String, dynamic>{
@ -31,12 +31,10 @@ Map<String, dynamic> _$AccountsStoreToJson(AccountsStore instance) =>
'defaultAccount': instance.defaultAccount,
};
UserData _$UserDataFromJson(Map<String, dynamic> json) {
return UserData(
jwt: Jwt.fromJson(json['jwt'] as String),
userId: json['userId'] as int,
);
}
UserData _$UserDataFromJson(Map<String, dynamic> json) => UserData(
jwt: Jwt.fromJson(json['jwt'] as String),
userId: json['userId'] as int,
);
Map<String, dynamic> _$UserDataToJson(UserData instance) => <String, dynamic>{
'jwt': instance.jwt,

View File

@ -6,18 +6,16 @@ part of 'config_store.dart';
// JsonSerializableGenerator
// **************************************************************************
ConfigStore _$ConfigStoreFromJson(Map<String, dynamic> json) {
return ConfigStore()
..theme = _$enumDecodeNullable(_$ThemeModeEnumMap, json['theme']) ??
ThemeMode.system
..amoledDarkMode = json['amoledDarkMode'] as bool? ?? false
..locale = LocaleSerde.fromJson(json['locale'] as String?)
..showAvatars = json['showAvatars'] as bool? ?? true
..showScores = json['showScores'] as bool? ?? true
..defaultSortType = _sortTypeFromJson(json['defaultSortType'] as String?)
..defaultListingType =
_postListingTypeFromJson(json['defaultListingType'] as String?);
}
ConfigStore _$ConfigStoreFromJson(Map<String, dynamic> json) => ConfigStore()
..theme = _$enumDecodeNullable(_$ThemeModeEnumMap, json['theme']) ??
ThemeMode.system
..amoledDarkMode = json['amoledDarkMode'] as bool? ?? false
..locale = LocaleSerde.fromJson(json['locale'] as String?)
..showAvatars = json['showAvatars'] as bool? ?? true
..showScores = json['showScores'] as bool? ?? true
..defaultSortType = _sortTypeFromJson(json['defaultSortType'] as String?)
..defaultListingType =
_postListingTypeFromJson(json['defaultListingType'] as String?);
Map<String, dynamic> _$ConfigStoreToJson(ConfigStore instance) =>
<String, dynamic>{

View File

@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'util/text_color.dart';
@ -9,6 +10,13 @@ ThemeData _themeFactory({bool dark = false, bool amoled = false}) {
final maybeAmoledColor = amoled ? Colors.black : null;
return theme.copyWith(
pageTransitionsTheme: const PageTransitionsTheme(
builders: {
TargetPlatform.android: CupertinoPageTransitionsBuilder(),
TargetPlatform.iOS: CupertinoPageTransitionsBuilder(),
TargetPlatform.fuchsia: CupertinoPageTransitionsBuilder(),
},
),
scaffoldBackgroundColor: maybeAmoledColor,
backgroundColor: maybeAmoledColor,
canvasColor: maybeAmoledColor,
@ -17,29 +25,30 @@ ThemeData _themeFactory({bool dark = false, bool amoled = false}) {
visualDensity: VisualDensity.adaptivePlatformDensity,
appBarTheme: AppBarTheme(
elevation: 0,
brightness: theme.brightness,
systemOverlayStyle: theme.brightness == Brightness.dark
? SystemUiOverlayStyle.light
: SystemUiOverlayStyle.dark,
color: Colors.transparent,
shadowColor: Colors.transparent,
centerTitle: true,
iconTheme: IconThemeData(color: theme.colorScheme.onSurface),
textTheme: TextTheme(
headline6: theme.textTheme.headline6
?.copyWith(fontSize: 20, fontWeight: FontWeight.w500),
),
titleTextStyle: theme.textTheme.headline6
?.copyWith(fontSize: 20, fontWeight: FontWeight.w500),
),
tabBarTheme: TabBarTheme(
unselectedLabelColor: Colors.grey,
labelColor: theme.colorScheme.onSurface,
),
chipTheme: ChipThemeData(
backgroundColor: theme.accentColor,
backgroundColor: theme.colorScheme.secondary,
disabledColor: Colors.amber,
selectedColor: Colors.amber,
secondarySelectedColor: Colors.amber,
padding: EdgeInsets.zero,
shape: const StadiumBorder(),
labelStyle:
TextStyle(color: textColorBasedOnBackground(theme.accentColor)),
labelStyle: TextStyle(
color: textColorBasedOnBackground(theme.colorScheme.secondary),
),
secondaryLabelStyle: const TextStyle(color: Colors.amber),
brightness: theme.brightness,
labelPadding: const EdgeInsets.symmetric(horizontal: 12),
@ -53,8 +62,8 @@ ThemeData _themeFactory({bool dark = false, bool amoled = false}) {
),
elevatedButtonTheme: ElevatedButtonThemeData(
style: ElevatedButton.styleFrom(
primary: theme.accentColor,
onPrimary: textColorBasedOnBackground(theme.accentColor),
primary: theme.colorScheme.secondary,
onPrimary: textColorBasedOnBackground(theme.colorScheme.secondary),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),

View File

@ -1,4 +1,3 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:url_launcher/url_launcher.dart' as ul;
@ -63,7 +62,6 @@ Future<void> linkLauncher({
return goToPost(context, matchedInstance, int.parse(split[2]));
} else if (split.length == 5) {
// TODO: post with focus on comment thread
print('comment in post');
return goToPost(context, matchedInstance, int.parse(split[2]));
}
break;
@ -73,21 +71,17 @@ Future<void> linkLauncher({
case 'communities':
// TODO: put here push to communities page
print('communities');
return;
case 'modlog':
// TODO: put here push to modlog
print('modlog');
return;
case 'inbox':
// TODO: put here push to inbox
print('inbox');
return;
case 'search':
// TODO: *maybe* put here push to search. we'll see
// how much web version differs form the app
print('search');
return;
case 'create_post':
case 'create_community':

View File

@ -19,10 +19,8 @@ abstract class _AsyncStore<T> with Store {
bool get isLoading => asyncState is AsyncStateLoading;
@computed
String? get errorTerm => asyncState.maybeWhen(
error: (errorTerm) => errorTerm,
orElse: () => null,
);
String? get errorTerm =>
asyncState.whenOrNull(error: (errorTerm) => errorTerm);
/// runs some async action and reflects the progress in [asyncState].
/// If successful, the result is returned, otherwise null is returned.

View File

@ -1,5 +1,6 @@
// coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target
part of 'async_store.dart';
@ -51,6 +52,14 @@ mixin _$AsyncState<T> {
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult Function()? initial,
TResult Function(T data)? data,
TResult Function()? loading,
TResult Function(String errorTerm)? error,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function()? initial,
TResult Function(T data)? data,
@ -68,6 +77,14 @@ mixin _$AsyncState<T> {
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult Function(AsyncStateInitial<T> value)? initial,
TResult Function(AsyncStateData<T> value)? data,
TResult Function(AsyncStateLoading<T> value)? loading,
TResult Function(AsyncStateError<T> value)? error,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(AsyncStateInitial<T> value)? initial,
TResult Function(AsyncStateData<T> value)? data,
@ -115,6 +132,7 @@ class _$AsyncStateInitialCopyWithImpl<T, $Res>
}
/// @nodoc
class _$AsyncStateInitial<T>
with DiagnosticableTreeMixin
implements AsyncStateInitial<T> {
@ -150,6 +168,17 @@ class _$AsyncStateInitial<T>
return initial();
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult Function()? initial,
TResult Function(T data)? data,
TResult Function()? loading,
TResult Function(String errorTerm)? error,
}) {
return initial?.call();
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
@ -176,6 +205,17 @@ class _$AsyncStateInitial<T>
return initial(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult Function(AsyncStateInitial<T> value)? initial,
TResult Function(AsyncStateData<T> value)? data,
TResult Function(AsyncStateLoading<T> value)? loading,
TResult Function(AsyncStateError<T> value)? error,
}) {
return initial?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
@ -229,6 +269,7 @@ class _$AsyncStateDataCopyWithImpl<T, $Res>
}
/// @nodoc
class _$AsyncStateData<T>
with DiagnosticableTreeMixin
implements AsyncStateData<T> {
@ -278,6 +319,17 @@ class _$AsyncStateData<T>
return data(this.data);
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult Function()? initial,
TResult Function(T data)? data,
TResult Function()? loading,
TResult Function(String errorTerm)? error,
}) {
return data?.call(this.data);
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
@ -304,6 +356,17 @@ class _$AsyncStateData<T>
return data(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult Function(AsyncStateInitial<T> value)? initial,
TResult Function(AsyncStateData<T> value)? data,
TResult Function(AsyncStateLoading<T> value)? loading,
TResult Function(AsyncStateError<T> value)? error,
}) {
return data?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
@ -349,6 +412,7 @@ class _$AsyncStateLoadingCopyWithImpl<T, $Res>
}
/// @nodoc
class _$AsyncStateLoading<T>
with DiagnosticableTreeMixin
implements AsyncStateLoading<T> {
@ -384,6 +448,17 @@ class _$AsyncStateLoading<T>
return loading();
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult Function()? initial,
TResult Function(T data)? data,
TResult Function()? loading,
TResult Function(String errorTerm)? error,
}) {
return loading?.call();
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
@ -410,6 +485,17 @@ class _$AsyncStateLoading<T>
return loading(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult Function(AsyncStateInitial<T> value)? initial,
TResult Function(AsyncStateData<T> value)? data,
TResult Function(AsyncStateLoading<T> value)? loading,
TResult Function(AsyncStateError<T> value)? error,
}) {
return loading?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
@ -463,6 +549,7 @@ class _$AsyncStateErrorCopyWithImpl<T, $Res>
}
/// @nodoc
class _$AsyncStateError<T>
with DiagnosticableTreeMixin
implements AsyncStateError<T> {
@ -513,6 +600,17 @@ class _$AsyncStateError<T>
return error(errorTerm);
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult Function()? initial,
TResult Function(T data)? data,
TResult Function()? loading,
TResult Function(String errorTerm)? error,
}) {
return error?.call(errorTerm);
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
@ -539,6 +637,17 @@ class _$AsyncStateError<T>
return error(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult Function(AsyncStateInitial<T> value)? initial,
TResult Function(AsyncStateData<T> value)? data,
TResult Function(AsyncStateLoading<T> value)? loading,
TResult Function(AsyncStateError<T> value)? error,
}) {
return error?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({

View File

@ -1,4 +1,4 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
/// Creates gaps between given widgets
extension SpaceWidgets on List<Widget> {

View File

@ -1,4 +1,3 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:lemmy_api_client/v3.dart';
@ -13,7 +12,7 @@ Future<dynamic> goTo(
BuildContext context,
Widget Function(BuildContext context) builder,
) =>
Navigator.of(context).push(CupertinoPageRoute(
Navigator.of(context).push(MaterialPageRoute(
builder: builder,
));
@ -22,7 +21,7 @@ Future<dynamic> goToReplace(
BuildContext context,
Widget Function(BuildContext context) builder,
) =>
Navigator.of(context).pushReplacement(CupertinoPageRoute(
Navigator.of(context).pushReplacement(MaterialPageRoute(
builder: builder,
));

View File

@ -1,6 +1,8 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:share/share.dart';
import 'package:share_plus/share_plus.dart';
/// A `package:share` wrapper that fallbacks to copying contents to the clipboard
/// on platforms that do not support native sharing
@ -10,16 +12,28 @@ Future<void> share(
Rect? sharePositionOrigin,
required BuildContext context,
}) async {
if (Platform.isLinux || Platform.isWindows) {
await _fallbackShare(text, context: context);
return;
}
try {
return await Share.share(
await Share.share(
text,
subject: subject,
sharePositionOrigin: sharePositionOrigin,
);
} on MissingPluginException {
await Clipboard.setData(ClipboardData(text: text));
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Copied data to clipboard!')),
);
await _fallbackShare(text, context: context);
}
}
Future<void> _fallbackShare(
String text, {
required BuildContext context,
}) async {
await Clipboard.setData(ClipboardData(text: text));
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Copied data to clipboard!')),
);
}

View File

@ -1,3 +0,0 @@
/// Explicitely indicate to the `unawaited_futures` lint
/// that the future is not awaited for on purpose
void unawaited<T>(Future<T> future) {}

View File

@ -1,12 +1,11 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:flutter_markdown/flutter_markdown.dart';
import 'package:package_info/package_info.dart';
import 'package:package_info_plus/package_info_plus.dart';
import '../gen/assets.gen.dart';
import '../hooks/memo_future.dart';
import '../pages/log_console_page/log_console_page.dart';
import '../url_launcher.dart';
import 'bottom_modal.dart';
@ -17,21 +16,7 @@ class AboutTile extends HookWidget {
@override
Widget build(BuildContext context) {
final packageInfoSnap = useMemoFuture(
() async {
try {
return await PackageInfo.fromPlatform();
} on MissingPluginException {
// when we get here it means PackageInfo does not support this platform
return PackageInfo(
appName: 'lemmur',
packageName: '',
version: '',
buildNumber: '',
);
}
},
);
final packageInfoSnap = useMemoFuture(PackageInfo.fromPlatform);
final assetBundle = DefaultAssetBundle.of(context);
final changelogSnap =
useMemoFuture(() => assetBundle.loadString('CHANGELOG.md'));
@ -87,7 +72,14 @@ class AboutTile extends HookWidget {
),
),
);
}, // TODO: link to some donation site
},
),
TextButton.icon(
icon: const Icon(Icons.list_alt),
label: const Text('logs'),
onPressed: () {
Navigator.of(context).push(LogConsolePage.route());
},
),
],
applicationIcon: ClipRRect(

View File

@ -2,9 +2,18 @@ import 'package:flutter/material.dart';
class BottomSafe extends StatelessWidget {
final double additionalPadding;
static const fabPadding =
// FAB size + FAB margin, 56 is as per https://material.io/components/buttons-floating-action-button#anatomy
56 + kFloatingActionButtonMargin;
const BottomSafe([this.additionalPadding = 0]);
const BottomSafe.fab() : this(fabPadding);
@override
Widget build(BuildContext context) => SizedBox(
height: MediaQuery.of(context).padding.bottom + additionalPadding);
Widget build(BuildContext context) {
return SizedBox(
height: MediaQuery.of(context).padding.bottom + additionalPadding,
);
}
}

View File

@ -1,6 +1,5 @@
import 'dart:math';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:lemmy_api_client/v3.dart';
import 'package:provider/provider.dart';
@ -240,7 +239,7 @@ class _CommentWidget extends StatelessWidget {
if (store.collapsed && store.children.isNotEmpty) ...[
_CommentTag(
'+${store.children.length}',
Theme.of(context).accentColor,
Theme.of(context).colorScheme.secondary,
),
const SizedBox(width: 7),
],

View File

@ -1,4 +1,3 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
@ -33,9 +32,8 @@ class CommentActions extends HookWidget {
final post = store.comment.post;
reply() async {
final newComment = await showCupertinoModalPopup<CommentView>(
context: context,
builder: (context) => WriteComment.toComment(
final newComment = await Navigator.of(context).push(
WriteComment.toCommentRoute(
comment: comment,
post: post,
),
@ -66,7 +64,9 @@ class CommentActions extends HookWidget {
TileAction(
icon: Icons.check,
onPressed: loggedInAction(store.markAsRead),
iconColor: comment.read ? Theme.of(context).accentColor : null,
iconColor: comment.read
? Theme.of(context).colorScheme.secondary
: null,
tooltip: comment.read
? L10n.of(context)!.mark_as_unread
: L10n.of(context)!.mark_as_read,
@ -95,7 +95,7 @@ class CommentActions extends HookWidget {
TileAction(
icon: Icons.arrow_upward,
iconColor: store.myVote == VoteType.up
? Theme.of(context).accentColor
? Theme.of(context).colorScheme.secondary
: null,
onPressed: loggedInAction(store.upVote),
tooltip: 'upvote',

View File

@ -1,4 +1,3 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:lemmy_api_client/v3.dart';
@ -63,9 +62,8 @@ class _CommentMoreMenuPopup extends HookWidget {
}
handleEdit() async {
final editedComment = await showCupertinoModalPopup<CommentView>(
context: context,
builder: (_) => WriteComment.edit(
final editedComment = await Navigator.of(context).push(
WriteComment.editRoute(
comment: comment,
post: post,
),

View File

@ -1,4 +1,3 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import '../pages/media_view.dart';

View File

@ -4,7 +4,6 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import '../hooks/ref.dart';
import 'bottom_safe.dart';
class InfiniteScrollController {
@ -77,9 +76,9 @@ class InfiniteScroll<T> extends HookWidget {
if (controller != null) {
controller?.clear = () {
data.value = [];
hasMore.current = true;
page.current = 1;
dataSet.current.clear();
hasMore.value = true;
page.value = 1;
dataSet.value.clear();
};
}
@ -89,9 +88,9 @@ class InfiniteScroll<T> extends HookWidget {
return RefreshIndicator(
onRefresh: () async {
data.value = [];
hasMore.current = true;
page.current = 1;
dataSet.current.clear();
hasMore.value = true;
page.value = 1;
dataSet.value.clear();
await HapticFeedback.mediumImpact();
await Future.delayed(const Duration(seconds: 1));
@ -107,35 +106,35 @@ class InfiniteScroll<T> extends HookWidget {
i -= 1;
// if we are done but we have no data it means the list is empty
if (!hasMore.current && data.value.isEmpty) {
if (!hasMore.value && data.value.isEmpty) {
return Center(child: noItems);
}
// reached the bottom, fetch more
if (i == data.value.length) {
// if there are no more, skip
if (!hasMore.current) {
if (!hasMore.value) {
return const BottomSafe();
}
// if it's already fetching more, skip
if (!isFetching.current) {
isFetching.current = true;
fetcher(page.current, batchSize).then((incoming) {
if (!isFetching.value) {
isFetching.value = true;
fetcher(page.value, batchSize).then((incoming) {
// if got less than the batchSize, mark the list as done
if (incoming.length < batchSize) {
hasMore.current = false;
hasMore.value = false;
}
final newData = incoming.where(
(e) => !dataSet.current.contains(uniquePropFunc(e)),
(e) => !dataSet.value.contains(uniquePropFunc(e)),
);
// append new data
data.value = [...data.value, ...newData];
dataSet.current.addAll(newData.map(uniquePropFunc));
page.current += 1;
}).whenComplete(() => isFetching.current = false);
dataSet.value.addAll(newData.map(uniquePropFunc));
page.value += 1;
}).whenComplete(() => isFetching.value = false);
}
return SafeArea(

View File

@ -30,7 +30,9 @@ void showInfoTablePopup({
),
child: Text(
'[tap to show]',
style: TextStyle(color: Theme.of(context).accentColor),
style: TextStyle(
color: Theme.of(context).colorScheme.secondary,
),
),
)
else

View File

@ -27,7 +27,9 @@ class MarkdownText extends StatelessWidget {
styleSheet: MarkdownStyleSheet.fromTheme(theme).copyWith(
blockquoteDecoration: BoxDecoration(
color: Colors.grey.withOpacity(0.3),
border: Border(left: BorderSide(width: 2, color: theme.accentColor)),
border: Border(
left: BorderSide(width: 2, color: theme.colorScheme.secondary),
),
),
code: theme.textTheme.bodyText1
// TODO: use a font from google fonts maybe? the defaults aren't very pretty

View File

@ -1,7 +1,6 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:lemmy_api_client/v3.dart';
import 'package:provider/provider.dart';
import 'package:url_launcher/url_launcher.dart' as ul;
@ -88,9 +87,8 @@ class PostMoreMenu extends HookWidget {
leading: const Icon(Icons.edit),
title: const Text('Edit'),
onTap: () async {
final postView = await showCupertinoModalPopup<PostView>(
context: context,
builder: (_) => CreatePostPage.edit(post.post),
final postView = await Navigator.of(context).push(
CreatePostPage.editRoute(post.post),
);
if (postView != null) {

View File

@ -31,10 +31,10 @@ class PostListOptions extends StatelessWidget {
),
const Spacer(),
if (styleButton)
IconButton(
icon: const Icon(Icons.view_stream),
const IconButton(
icon: Icon(Icons.view_stream),
// TODO: create compact post and dropdown for selecting
onPressed: () => print('TBD'),
onPressed: null,
),
],
),

View File

@ -137,7 +137,7 @@ class _UserOverview extends HookWidget {
Widget build(BuildContext context) {
final theme = Theme.of(context);
final colorOnTopOfAccentColor =
textColorBasedOnBackground(theme.accentColor);
textColorBasedOnBackground(theme.colorScheme.secondary);
return Stack(
children: [
@ -154,7 +154,7 @@ class _UserOverview extends HookWidget {
Container(
width: double.infinity,
height: 200,
color: theme.accentColor,
color: theme.colorScheme.secondary,
),
Container(
height: 200,

View File

@ -134,4 +134,28 @@ class WriteComment extends HookWidget {
),
);
}
static Route<CommentView> toPostRoute(Post post) => MaterialPageRoute(
builder: (context) => WriteComment.toPost(post),
fullscreenDialog: true,
);
static Route<CommentView> toCommentRoute({
required Comment comment,
required Post post,
}) =>
MaterialPageRoute(
builder: (context) =>
WriteComment.toComment(comment: comment, post: post),
fullscreenDialog: true,
);
static Route<CommentView> editRoute({
required Comment comment,
required Post post,
}) =>
MaterialPageRoute(
builder: (context) => WriteComment.edit(comment: comment, post: post),
fullscreenDialog: true,
);
}

View File

@ -82,7 +82,7 @@ add_custom_command(
COMMAND ${CMAKE_COMMAND} -E env
${FLUTTER_TOOL_ENVIRONMENT}
"${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh"
linux-x64 ${CMAKE_BUILD_TYPE}
${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE}
VERBATIM
)
add_custom_target(flutter_assemble DEPENDS

View File

@ -2,6 +2,8 @@
// Generated file. Do not edit.
//
// clang-format off
#include "generated_plugin_registrant.h"
#include <url_launcher_linux/url_launcher_plugin.h>

View File

@ -2,6 +2,8 @@
// Generated file. Do not edit.
//
// clang-format off
#ifndef GENERATED_PLUGIN_REGISTRANT_
#define GENERATED_PLUGIN_REGISTRANT_

View File

@ -7,14 +7,14 @@ packages:
name: _fe_analyzer_shared
url: "https://pub.dartlang.org"
source: hosted
version: "22.0.0"
version: "25.0.0"
analyzer:
dependency: transitive
description:
name: analyzer
url: "https://pub.dartlang.org"
source: hosted
version: "1.7.1"
version: "2.2.0"
archive:
dependency: transitive
description:
@ -28,14 +28,14 @@ packages:
name: args
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
version: "2.2.0"
async:
dependency: transitive
description:
name: async
url: "https://pub.dartlang.org"
source: hosted
version: "2.6.1"
version: "2.8.1"
boolean_selector:
dependency: transitive
description:
@ -49,63 +49,77 @@ packages:
name: build
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
version: "2.1.0"
build_config:
dependency: transitive
description:
name: build_config
url: "https://pub.dartlang.org"
source: hosted
version: "0.4.7"
version: "1.0.0"
build_daemon:
dependency: transitive
description:
name: build_daemon
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.10"
version: "3.0.0"
build_resolvers:
dependency: transitive
description:
name: build_resolvers
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
version: "2.0.4"
build_runner:
dependency: "direct dev"
description:
name: build_runner
url: "https://pub.dartlang.org"
source: hosted
version: "1.12.2"
version: "2.1.2"
build_runner_core:
dependency: transitive
description:
name: build_runner_core
url: "https://pub.dartlang.org"
source: hosted
version: "6.1.12"
version: "7.1.0"
built_collection:
dependency: transitive
description:
name: built_collection
url: "https://pub.dartlang.org"
source: hosted
version: "5.0.0"
version: "5.1.1"
built_value:
dependency: transitive
description:
name: built_value
url: "https://pub.dartlang.org"
source: hosted
version: "8.0.4"
version: "8.1.2"
cached_network_image:
dependency: "direct main"
description:
name: cached_network_image
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.0"
version: "3.1.0"
cached_network_image_platform_interface:
dependency: transitive
description:
name: cached_network_image_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
cached_network_image_web:
dependency: transitive
description:
name: cached_network_image_web
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.1"
characters:
dependency: transitive
description:
@ -119,7 +133,7 @@ packages:
name: charcode
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
version: "1.3.1"
checked_yaml:
dependency: transitive
description:
@ -133,7 +147,7 @@ packages:
name: cli_util
url: "https://pub.dartlang.org"
source: hosted
version: "0.3.0"
version: "0.3.3"
clock:
dependency: transitive
description:
@ -147,7 +161,7 @@ packages:
name: code_builder
url: "https://pub.dartlang.org"
source: hosted
version: "3.7.0"
version: "4.1.0"
collection:
dependency: transitive
description:
@ -161,7 +175,14 @@ packages:
name: convert
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.0"
version: "3.0.1"
cross_file:
dependency: transitive
description:
name: cross_file
url: "https://pub.dartlang.org"
source: hosted
version: "0.3.1+5"
crypto:
dependency: transitive
description:
@ -175,14 +196,14 @@ packages:
name: cupertino_icons
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.2"
version: "1.0.3"
dart_style:
dependency: transitive
description:
name: dart_style
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
version: "2.1.0"
fake_async:
dependency: transitive
description:
@ -196,14 +217,14 @@ packages:
name: ffi
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
version: "1.1.2"
file:
dependency: transitive
description:
name: file
url: "https://pub.dartlang.org"
source: hosted
version: "6.1.0"
version: "6.1.2"
fixnum:
dependency: transitive
description:
@ -229,21 +250,21 @@ packages:
name: flutter_cache_manager
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.1"
version: "3.1.2"
flutter_hooks:
dependency: "direct main"
description:
name: flutter_hooks
url: "https://pub.dartlang.org"
source: hosted
version: "0.16.0"
version: "0.18.0"
flutter_launcher_icons:
dependency: "direct dev"
description:
name: flutter_launcher_icons
url: "https://pub.dartlang.org"
source: hosted
version: "0.9.0"
version: "0.9.2"
flutter_localizations:
dependency: "direct main"
description: flutter
@ -255,7 +276,7 @@ packages:
name: flutter_markdown
url: "https://pub.dartlang.org"
source: hosted
version: "0.6.1"
version: "0.6.6"
flutter_mobx:
dependency: "direct main"
description:
@ -269,14 +290,14 @@ packages:
name: flutter_plugin_android_lifecycle
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.1"
version: "2.0.3"
flutter_speed_dial:
dependency: "direct main"
description:
name: flutter_speed_dial
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.5"
version: "4.3.0"
flutter_test:
dependency: "direct dev"
description: flutter
@ -293,14 +314,21 @@ packages:
name: freezed
url: "https://pub.dartlang.org"
source: hosted
version: "0.14.1+2"
version: "0.14.5"
freezed_annotation:
dependency: "direct main"
description:
name: freezed_annotation
url: "https://pub.dartlang.org"
source: hosted
version: "0.14.2"
version: "0.14.3"
frontend_server_client:
dependency: transitive
description:
name: frontend_server_client
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.2"
fuzzy:
dependency: "direct main"
description:
@ -321,21 +349,21 @@ packages:
name: graphs
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
version: "2.0.0"
http:
dependency: transitive
description:
name: http
url: "https://pub.dartlang.org"
source: hosted
version: "0.13.1"
version: "0.13.3"
http_multi_server:
dependency: transitive
description:
name: http_multi_server
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.0"
version: "3.0.1"
http_parser:
dependency: transitive
description:
@ -349,28 +377,28 @@ packages:
name: image
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.2"
version: "3.0.4"
image_picker:
dependency: "direct main"
description:
name: image_picker
url: "https://pub.dartlang.org"
source: hosted
version: "0.7.4"
version: "0.8.4"
image_picker_for_web:
dependency: transitive
description:
name: image_picker_for_web
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
version: "2.1.3"
image_picker_platform_interface:
dependency: transitive
description:
name: image_picker_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.1"
version: "2.4.1"
intl:
dependency: "direct main"
description:
@ -384,7 +412,7 @@ packages:
name: io
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
version: "1.0.3"
js:
dependency: transitive
description:
@ -398,14 +426,14 @@ packages:
name: json_annotation
url: "https://pub.dartlang.org"
source: hosted
version: "4.0.1"
version: "4.1.0"
json_serializable:
dependency: "direct dev"
description:
name: json_serializable
url: "https://pub.dartlang.org"
source: hosted
version: "4.1.0"
version: "5.0.0"
keyboard_dismisser:
dependency: "direct main"
description:
@ -428,7 +456,7 @@ packages:
source: hosted
version: "0.16.0"
logging:
dependency: transitive
dependency: "direct main"
description:
name: logging
url: "https://pub.dartlang.org"
@ -461,7 +489,7 @@ packages:
name: meta
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.0"
version: "1.7.0"
mime:
dependency: transitive
description:
@ -482,7 +510,7 @@ packages:
name: mobx_codegen
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.2"
version: "2.0.3"
modal_bottom_sheet:
dependency: "direct main"
description:
@ -511,13 +539,48 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
package_info:
package_info_plus:
dependency: "direct main"
description:
name: package_info
name: package_info_plus
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
version: "1.0.6"
package_info_plus_linux:
dependency: transitive
description:
name: package_info_plus_linux
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.3"
package_info_plus_macos:
dependency: transitive
description:
name: package_info_plus_macos
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.1"
package_info_plus_platform_interface:
dependency: transitive
description:
name: package_info_plus_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.2"
package_info_plus_web:
dependency: transitive
description:
name: package_info_plus_web
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.4"
package_info_plus_windows:
dependency: transitive
description:
name: package_info_plus_windows
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.3"
path:
dependency: transitive
description:
@ -531,21 +594,21 @@ packages:
name: path_provider
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.1"
version: "2.0.3"
path_provider_linux:
dependency: transitive
description:
name: path_provider_linux
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
version: "2.0.2"
path_provider_macos:
dependency: transitive
description:
name: path_provider_macos
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
version: "2.0.2"
path_provider_platform_interface:
dependency: transitive
description:
@ -559,42 +622,44 @@ packages:
name: path_provider_windows
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
version: "2.0.3"
pedantic:
dependency: transitive
description:
name: pedantic
url: "https://pub.dartlang.org"
source: hosted
version: "1.11.0"
version: "1.11.1"
petitparser:
dependency: transitive
description:
name: petitparser
url: "https://pub.dartlang.org"
source: hosted
version: "4.1.0"
version: "4.3.0"
photo_view:
dependency: "direct main"
description:
name: photo_view
url: "https://pub.dartlang.org"
source: hosted
version: "0.11.1"
path: "."
ref: "bugfix/flutter-2.5-update"
resolved-ref: "6c9aee42e1d6d7be7fbd53e9df47e46d3efc81b6"
url: "https://github.com/karvulf/photo_view"
source: git
version: "0.12.0"
platform:
dependency: transitive
description:
name: platform
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.0"
version: "3.0.2"
plugin_platform_interface:
dependency: transitive
description:
name: plugin_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
version: "2.0.1"
pool:
dependency: transitive
description:
@ -608,14 +673,14 @@ packages:
name: process
url: "https://pub.dartlang.org"
source: hosted
version: "4.2.1"
version: "4.2.3"
provider:
dependency: "direct main"
description:
name: provider
url: "https://pub.dartlang.org"
source: hosted
version: "5.0.0"
version: "6.0.0"
pub_semver:
dependency: transitive
description:
@ -636,35 +701,70 @@ packages:
name: rxdart
url: "https://pub.dartlang.org"
source: hosted
version: "0.26.0"
share:
version: "0.27.2"
share_plus:
dependency: "direct main"
description:
name: share
name: share_plus
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.4"
share_plus_linux:
dependency: transitive
description:
name: share_plus_linux
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.4"
share_plus_macos:
dependency: transitive
description:
name: share_plus_macos
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.2"
share_plus_platform_interface:
dependency: transitive
description:
name: share_plus_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.1"
share_plus_web:
dependency: transitive
description:
name: share_plus_web
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.4"
share_plus_windows:
dependency: transitive
description:
name: share_plus_windows
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.3"
shared_preferences:
dependency: "direct main"
description:
name: shared_preferences
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.5"
version: "2.0.7"
shared_preferences_linux:
dependency: transitive
description:
name: shared_preferences_linux
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
version: "2.0.2"
shared_preferences_macos:
dependency: transitive
description:
name: shared_preferences_macos
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
version: "2.0.2"
shared_preferences_platform_interface:
dependency: transitive
description:
@ -678,21 +778,21 @@ packages:
name: shared_preferences_web
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
version: "2.0.2"
shared_preferences_windows:
dependency: transitive
description:
name: shared_preferences_windows
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
version: "2.0.2"
shelf:
dependency: transitive
description:
name: shelf
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
version: "1.2.0"
shelf_web_socket:
dependency: transitive
description:
@ -711,7 +811,14 @@ packages:
name: source_gen
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
version: "1.1.0"
source_helper:
dependency: transitive
description:
name: source_helper
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.1"
source_span:
dependency: transitive
description:
@ -725,14 +832,14 @@ packages:
name: sqflite
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0+3"
version: "2.0.0+4"
sqflite_common:
dependency: transitive
description:
name: sqflite_common
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0+2"
version: "2.0.1+1"
stack_trace:
dependency: transitive
description:
@ -781,14 +888,14 @@ packages:
name: test_api
url: "https://pub.dartlang.org"
source: hosted
version: "0.3.0"
version: "0.4.2"
timeago:
dependency: "direct main"
description:
name: timeago
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.2"
version: "3.1.0"
timing:
dependency: transitive
description:
@ -809,49 +916,49 @@ packages:
name: url_launcher
url: "https://pub.dartlang.org"
source: hosted
version: "6.0.3"
version: "6.0.10"
url_launcher_linux:
dependency: transitive
description:
name: url_launcher_linux
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
version: "2.0.2"
url_launcher_macos:
dependency: transitive
description:
name: url_launcher_macos
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
version: "2.0.2"
url_launcher_platform_interface:
dependency: transitive
description:
name: url_launcher_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.2"
version: "2.0.4"
url_launcher_web:
dependency: transitive
description:
name: url_launcher_web
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
version: "2.0.4"
url_launcher_windows:
dependency: transitive
description:
name: url_launcher_windows
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
version: "2.0.2"
uuid:
dependency: transitive
description:
name: uuid
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.3"
version: "3.0.4"
vector_math:
dependency: transitive
description:
@ -872,14 +979,14 @@ packages:
name: web_socket_channel
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
version: "2.1.0"
win32:
dependency: transitive
description:
name: win32
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.5"
version: "2.2.9"
xdg_directories:
dependency: transitive
description:
@ -893,7 +1000,7 @@ packages:
name: xml
url: "https://pub.dartlang.org"
source: hosted
version: "5.1.0"
version: "5.3.0"
yaml:
dependency: transitive
description:
@ -902,5 +1009,5 @@ packages:
source: hosted
version: "3.1.0"
sdks:
dart: ">=2.12.0 <3.0.0"
flutter: ">=1.24.0-10.2.pre"
dart: ">=2.14.0 <3.0.0"
flutter: ">=2.0.0"

View File

@ -18,27 +18,31 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
version: 0.6.0+17
environment:
sdk: ">=2.12.0 <3.0.0"
sdk: ">=2.14.0 <3.0.0"
dependencies:
# widgets
flutter_speed_dial: ^3.0.5
photo_view: ^0.11.1
flutter_speed_dial: ^4.3.0
# TODO: bring back to pub hosted when fix is released
photo_view:
git:
url: https://github.com/karvulf/photo_view
ref: bugfix/flutter-2.5-update
markdown: ^4.0.0
flutter_markdown: ^0.6.1
cached_network_image: ^3.0.0
modal_bottom_sheet: ^2.0.0
# native
share: ^2.0.1
share_plus: ^2.1.4
url_launcher: ^6.0.3
shared_preferences: ^2.0.5
package_info: ^2.0.0
image_picker: ^0.7.4
package_info_plus: ^1.0.6
image_picker: ^0.8.4
# state management
flutter_hooks: ^0.16.0
provider: ^5.0.0
flutter_hooks: ^0.18.0
provider: ^6.0.0
mobx: ^2.0.4
flutter_mobx: ^2.0.2
@ -48,9 +52,10 @@ dependencies:
lemmy_api_client: ^0.16.0
intl: ^0.17.0
matrix4_transform: ^2.0.0
json_annotation: ^4.0.1
json_annotation: ^4.1.0
keyboard_dismisser: ^2.0.0
freezed_annotation: ^0.14.2
freezed_annotation: ^0.14.3
logging: ^1.0.1
flutter:
sdk: flutter
@ -64,9 +69,9 @@ dependencies:
dev_dependencies:
flutter_test:
sdk: flutter
flutter_launcher_icons: ^0.9.0
json_serializable: ^4.1.0
build_runner: ^1.11.1
flutter_launcher_icons: ^0.9.2
json_serializable: ^5.0.0
build_runner: ^2.1.2
mobx_codegen: ^2.0.2
freezed: ^0.14.1+2

View File

@ -1,3 +1,4 @@
// ignore_for_file: avoid_print
import 'dart:io';
void confirm(String message) {

View File

@ -1,3 +1,4 @@
// ignore_for_file: avoid_print
/// Used to create a new lemmur release. Bumps semver, build number, updates changelog, fastlane, pubspec, and finishes by adding a git tag
import 'dart:io';