Compare commits
5 Commits
Author | SHA1 | Date | |
---|---|---|---|
fff756cbe0 | |||
e38778dbf9 | |||
cc9081b011 | |||
14e8f7b775 | |||
a70e6c7118 |
BIN
android/app/src/main/res/drawable-hdpi/splash.png
Normal file
After Width: | Height: | Size: 75 KiB |
BIN
android/app/src/main/res/drawable-mdpi/splash.png
Normal file
After Width: | Height: | Size: 39 KiB |
BIN
android/app/src/main/res/drawable-night-v21/background.png
Normal file
After Width: | Height: | Size: 69 B |
@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item>
|
||||||
|
<bitmap android:gravity="fill" android:src="@drawable/background"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<bitmap android:gravity="center" android:src="@drawable/splash"/>
|
||||||
|
</item>
|
||||||
|
</layer-list>
|
BIN
android/app/src/main/res/drawable-night/background.png
Normal file
After Width: | Height: | Size: 69 B |
@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item>
|
||||||
|
<bitmap android:gravity="fill" android:src="@drawable/background"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<bitmap android:gravity="center" android:src="@drawable/splash"/>
|
||||||
|
</item>
|
||||||
|
</layer-list>
|
BIN
android/app/src/main/res/drawable-v21/background.png
Normal file
After Width: | Height: | Size: 69 B |
@ -1,12 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?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">
|
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<item android:drawable="?android:colorBackground" />
|
<item>
|
||||||
|
<bitmap android:gravity="fill" android:src="@drawable/background"/>
|
||||||
<!-- You can insert your own image assets here -->
|
</item>
|
||||||
<!-- <item>
|
<item>
|
||||||
<bitmap
|
<bitmap android:gravity="center" android:src="@drawable/splash"/>
|
||||||
android:gravity="center"
|
</item>
|
||||||
android:src="@mipmap/launch_image" />
|
|
||||||
</item> -->
|
|
||||||
</layer-list>
|
</layer-list>
|
||||||
|
BIN
android/app/src/main/res/drawable-xhdpi/splash.png
Normal file
After Width: | Height: | Size: 117 KiB |
BIN
android/app/src/main/res/drawable-xxhdpi/splash.png
Normal file
After Width: | Height: | Size: 233 KiB |
BIN
android/app/src/main/res/drawable-xxxhdpi/splash.png
Normal file
After Width: | Height: | Size: 355 KiB |
BIN
android/app/src/main/res/drawable/background.png
Normal file
After Width: | Height: | Size: 69 B |
@ -1,12 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?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">
|
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<item android:drawable="@android:color/white" />
|
<item>
|
||||||
|
<bitmap android:gravity="fill" android:src="@drawable/background"/>
|
||||||
<!-- You can insert your own image assets here -->
|
</item>
|
||||||
<!-- <item>
|
<item>
|
||||||
<bitmap
|
<bitmap android:gravity="center" android:src="@drawable/splash"/>
|
||||||
android:gravity="center"
|
</item>
|
||||||
android:src="@mipmap/launch_image" />
|
|
||||||
</item> -->
|
|
||||||
</layer-list>
|
</layer-list>
|
||||||
|
19
android/app/src/main/res/values-night-v31/styles.xml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?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">
|
||||||
|
<item name="android:forceDarkAllowed">false</item>
|
||||||
|
<item name="android:windowFullscreen">false</item>
|
||||||
|
<item name="android:windowDrawsSystemBarBackgrounds">false</item>
|
||||||
|
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</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>
|
@ -5,6 +5,10 @@
|
|||||||
<!-- Show a splash screen on the activity. Automatically removed when
|
<!-- Show a splash screen on the activity. Automatically removed when
|
||||||
the Flutter engine draws its first frame -->
|
the Flutter engine draws its first frame -->
|
||||||
<item name="android:windowBackground">@drawable/launch_background</item>
|
<item name="android:windowBackground">@drawable/launch_background</item>
|
||||||
|
<item name="android:forceDarkAllowed">false</item>
|
||||||
|
<item name="android:windowFullscreen">false</item>
|
||||||
|
<item name="android:windowDrawsSystemBarBackgrounds">false</item>
|
||||||
|
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
|
||||||
</style>
|
</style>
|
||||||
<!-- Theme applied to the Android Window as soon as the process has started.
|
<!-- Theme applied to the Android Window as soon as the process has started.
|
||||||
This theme determines the color of the Android Window while your
|
This theme determines the color of the Android Window while your
|
||||||
|
19
android/app/src/main/res/values-v31/styles.xml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?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 off -->
|
||||||
|
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
||||||
|
<item name="android:forceDarkAllowed">false</item>
|
||||||
|
<item name="android:windowFullscreen">false</item>
|
||||||
|
<item name="android:windowDrawsSystemBarBackgrounds">false</item>
|
||||||
|
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</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.Light.NoTitleBar">
|
||||||
|
<item name="android:windowBackground">?android:colorBackground</item>
|
||||||
|
</style>
|
||||||
|
</resources>
|
@ -5,6 +5,10 @@
|
|||||||
<!-- Show a splash screen on the activity. Automatically removed when
|
<!-- Show a splash screen on the activity. Automatically removed when
|
||||||
the Flutter engine draws its first frame -->
|
the Flutter engine draws its first frame -->
|
||||||
<item name="android:windowBackground">@drawable/launch_background</item>
|
<item name="android:windowBackground">@drawable/launch_background</item>
|
||||||
|
<item name="android:forceDarkAllowed">false</item>
|
||||||
|
<item name="android:windowFullscreen">false</item>
|
||||||
|
<item name="android:windowDrawsSystemBarBackgrounds">false</item>
|
||||||
|
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
|
||||||
</style>
|
</style>
|
||||||
<!-- Theme applied to the Android Window as soon as the process has started.
|
<!-- Theme applied to the Android Window as soon as the process has started.
|
||||||
This theme determines the color of the Android Window while your
|
This theme determines the color of the Android Window while your
|
||||||
|
@ -157,6 +157,8 @@ PODS:
|
|||||||
- Flutter (1.0.0)
|
- Flutter (1.0.0)
|
||||||
- flutter_keyboard_visibility (0.0.1):
|
- flutter_keyboard_visibility (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
|
- flutter_native_splash (0.0.1):
|
||||||
|
- Flutter
|
||||||
- flutter_secure_storage (6.0.0):
|
- flutter_secure_storage (6.0.0):
|
||||||
- Flutter
|
- Flutter
|
||||||
- flutter_webrtc (0.11.3):
|
- flutter_webrtc (0.11.3):
|
||||||
@ -288,6 +290,7 @@ DEPENDENCIES:
|
|||||||
- firebase_performance (from `.symlinks/plugins/firebase_performance/ios`)
|
- firebase_performance (from `.symlinks/plugins/firebase_performance/ios`)
|
||||||
- Flutter (from `Flutter`)
|
- Flutter (from `Flutter`)
|
||||||
- flutter_keyboard_visibility (from `.symlinks/plugins/flutter_keyboard_visibility/ios`)
|
- flutter_keyboard_visibility (from `.symlinks/plugins/flutter_keyboard_visibility/ios`)
|
||||||
|
- flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`)
|
||||||
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
|
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
|
||||||
- flutter_webrtc (from `.symlinks/plugins/flutter_webrtc/ios`)
|
- flutter_webrtc (from `.symlinks/plugins/flutter_webrtc/ios`)
|
||||||
- gal (from `.symlinks/plugins/gal/darwin`)
|
- gal (from `.symlinks/plugins/gal/darwin`)
|
||||||
@ -361,6 +364,8 @@ EXTERNAL SOURCES:
|
|||||||
:path: Flutter
|
:path: Flutter
|
||||||
flutter_keyboard_visibility:
|
flutter_keyboard_visibility:
|
||||||
:path: ".symlinks/plugins/flutter_keyboard_visibility/ios"
|
:path: ".symlinks/plugins/flutter_keyboard_visibility/ios"
|
||||||
|
flutter_native_splash:
|
||||||
|
:path: ".symlinks/plugins/flutter_native_splash/ios"
|
||||||
flutter_secure_storage:
|
flutter_secure_storage:
|
||||||
:path: ".symlinks/plugins/flutter_secure_storage/ios"
|
:path: ".symlinks/plugins/flutter_secure_storage/ios"
|
||||||
flutter_webrtc:
|
flutter_webrtc:
|
||||||
@ -433,6 +438,7 @@ SPEC CHECKSUMS:
|
|||||||
FirebaseSharedSwift: 20530f495084b8d840f78a100d8c5ee613375f6e
|
FirebaseSharedSwift: 20530f495084b8d840f78a100d8c5ee613375f6e
|
||||||
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
|
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
|
||||||
flutter_keyboard_visibility: 0339d06371254c3eb25eeb90ba8d17dca8f9c069
|
flutter_keyboard_visibility: 0339d06371254c3eb25eeb90ba8d17dca8f9c069
|
||||||
|
flutter_native_splash: edf599c81f74d093a4daf8e17bd7a018854bc778
|
||||||
flutter_secure_storage: d33dac7ae2ea08509be337e775f6b59f1ff45f12
|
flutter_secure_storage: d33dac7ae2ea08509be337e775f6b59f1ff45f12
|
||||||
flutter_webrtc: 75b868e4f9e817c7a9a42ca4b6169063de4eec9f
|
flutter_webrtc: 75b868e4f9e817c7a9a42ca4b6169063de4eec9f
|
||||||
gal: 61e868295d28fe67ffa297fae6dacebf56fd53e1
|
gal: 61e868295d28fe67ffa297fae6dacebf56fd53e1
|
||||||
|
22
ios/Runner/Assets.xcassets/LaunchBackground.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "background.png",
|
||||||
|
"idiom" : "universal"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"appearances" : [
|
||||||
|
{
|
||||||
|
"appearance" : "luminosity",
|
||||||
|
"value" : "dark"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"filename" : "darkbackground.png",
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
BIN
ios/Runner/Assets.xcassets/LaunchBackground.imageset/background.png
vendored
Normal file
After Width: | Height: | Size: 69 B |
BIN
ios/Runner/Assets.xcassets/LaunchBackground.imageset/darkbackground.png
vendored
Normal file
After Width: | Height: | Size: 69 B |
@ -1,23 +1,23 @@
|
|||||||
{
|
{
|
||||||
"images" : [
|
"images" : [
|
||||||
{
|
{
|
||||||
"idiom" : "universal",
|
|
||||||
"filename" : "LaunchImage.png",
|
"filename" : "LaunchImage.png",
|
||||||
|
"idiom" : "universal",
|
||||||
"scale" : "1x"
|
"scale" : "1x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idiom" : "universal",
|
|
||||||
"filename" : "LaunchImage@2x.png",
|
"filename" : "LaunchImage@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
"scale" : "2x"
|
"scale" : "2x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idiom" : "universal",
|
|
||||||
"filename" : "LaunchImage@3x.png",
|
"filename" : "LaunchImage@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
"scale" : "3x"
|
"scale" : "3x"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"info" : {
|
"info" : {
|
||||||
"version" : 1,
|
"author" : "xcode",
|
||||||
"author" : "xcode"
|
"version" : 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Before Width: | Height: | Size: 68 B After Width: | Height: | Size: 39 KiB |
Before Width: | Height: | Size: 68 B After Width: | Height: | Size: 117 KiB |
Before Width: | Height: | Size: 68 B After Width: | Height: | Size: 233 KiB |
@ -16,13 +16,19 @@
|
|||||||
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
|
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4">
|
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" image="LaunchBackground" translatesAutoresizingMaskIntoConstraints="NO" id="tWc-Dq-wcI"/>
|
||||||
</imageView>
|
<imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4"></imageView>
|
||||||
</subviews>
|
</subviews>
|
||||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="1a2-6s-vTC"/>
|
<constraint firstItem="YRO-k0-Ey4" firstAttribute="leading" secondItem="Ze5-6b-2t3" secondAttribute="leading" id="3T2-ad-Qdv"/>
|
||||||
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="4X2-HB-R7a"/>
|
<constraint firstItem="tWc-Dq-wcI" firstAttribute="bottom" secondItem="Ze5-6b-2t3" secondAttribute="bottom" id="RPx-PI-7Xg"/>
|
||||||
|
<constraint firstItem="tWc-Dq-wcI" firstAttribute="top" secondItem="Ze5-6b-2t3" secondAttribute="top" id="SdS-ul-q2q"/>
|
||||||
|
<constraint firstAttribute="trailing" secondItem="tWc-Dq-wcI" secondAttribute="trailing" id="Swv-Gf-Rwn"/>
|
||||||
|
<constraint firstAttribute="trailing" secondItem="YRO-k0-Ey4" secondAttribute="trailing" id="TQA-XW-tRk"/>
|
||||||
|
<constraint firstItem="YRO-k0-Ey4" firstAttribute="bottom" secondItem="Ze5-6b-2t3" secondAttribute="bottom" id="duK-uY-Gun"/>
|
||||||
|
<constraint firstItem="tWc-Dq-wcI" firstAttribute="leading" secondItem="Ze5-6b-2t3" secondAttribute="leading" id="kV7-tw-vXt"/>
|
||||||
|
<constraint firstItem="YRO-k0-Ey4" firstAttribute="top" secondItem="Ze5-6b-2t3" secondAttribute="top" id="xPn-NY-SIU"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
</view>
|
</view>
|
||||||
</viewController>
|
</viewController>
|
||||||
@ -32,6 +38,7 @@
|
|||||||
</scene>
|
</scene>
|
||||||
</scenes>
|
</scenes>
|
||||||
<resources>
|
<resources>
|
||||||
<image name="LaunchImage" width="168" height="185"/>
|
<image name="LaunchImage" width="1026" height="1024"/>
|
||||||
|
<image name="LaunchBackground" width="1" height="1"/>
|
||||||
</resources>
|
</resources>
|
||||||
</document>
|
</document>
|
||||||
|
@ -1,85 +1,87 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?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">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
<key>CFBundleURLTypes</key>
|
<key>CFBundleURLTypes</key>
|
||||||
<array>
|
<array>
|
||||||
<dict>
|
<dict>
|
||||||
<key>CFBundleURLName</key>
|
<key>CFBundleURLName</key>
|
||||||
<string></string>
|
<string></string>
|
||||||
<key>CFBundleTypeRole</key>
|
<key>CFBundleTypeRole</key>
|
||||||
<string>Editor</string>
|
<string>Editor</string>
|
||||||
<key>CFBundleURLSchemes</key>
|
<key>CFBundleURLSchemes</key>
|
||||||
<array>
|
<array>
|
||||||
<string>solink</string>
|
<string>solink</string>
|
||||||
</array>
|
</array>
|
||||||
</dict>
|
</dict>
|
||||||
</array>
|
</array>
|
||||||
<key>FirebaseMessagingAutoInitEnabled</key>
|
<key>FirebaseMessagingAutoInitEnabled</key>
|
||||||
<false/>
|
<false/>
|
||||||
<key>CADisableMinimumFrameDurationOnPhone</key>
|
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>CFBundleDevelopmentRegion</key>
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||||
<key>CFBundleDisplayName</key>
|
<key>CFBundleDisplayName</key>
|
||||||
<string>Solian</string>
|
<string>Solian</string>
|
||||||
<key>CFBundleExecutable</key>
|
<key>CFBundleExecutable</key>
|
||||||
<string>$(EXECUTABLE_NAME)</string>
|
<string>$(EXECUTABLE_NAME)</string>
|
||||||
<key>CFBundleIdentifier</key>
|
<key>CFBundleIdentifier</key>
|
||||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||||
<key>CFBundleInfoDictionaryVersion</key>
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
<string>6.0</string>
|
<string>6.0</string>
|
||||||
<key>CFBundleName</key>
|
<key>CFBundleName</key>
|
||||||
<string>solian</string>
|
<string>solian</string>
|
||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>APPL</string>
|
<string>APPL</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>$(FLUTTER_BUILD_NAME)</string>
|
<string>$(FLUTTER_BUILD_NAME)</string>
|
||||||
<key>CFBundleSignature</key>
|
<key>CFBundleSignature</key>
|
||||||
<string>????</string>
|
<string>????</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
||||||
<key>ITSAppUsesNonExemptEncryption</key>
|
<key>ITSAppUsesNonExemptEncryption</key>
|
||||||
<false/>
|
<false/>
|
||||||
<key>LSRequiresIPhoneOS</key>
|
<key>LSRequiresIPhoneOS</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>NSCameraUsageDescription</key>
|
<key>NSCameraUsageDescription</key>
|
||||||
<string>Allow you take photo/video for your message or post</string>
|
<string>Allow you take photo/video for your message or post</string>
|
||||||
<key>NSMicrophoneUsageDescription</key>
|
<key>NSMicrophoneUsageDescription</key>
|
||||||
<string>Allow you record audio for your message or post</string>
|
<string>Allow you record audio for your message or post</string>
|
||||||
<key>NSPhotoLibraryUsageDescription</key>
|
<key>NSPhotoLibraryUsageDescription</key>
|
||||||
<string>Allow you add photo to your message or post</string>
|
<string>Allow you add photo to your message or post</string>
|
||||||
<key>UIApplicationSupportsIndirectInputEvents</key>
|
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>UIBackgroundModes</key>
|
<key>UIBackgroundModes</key>
|
||||||
<array>
|
<array>
|
||||||
<string>audio</string>
|
<string>audio</string>
|
||||||
<string>fetch</string>
|
<string>fetch</string>
|
||||||
<string>remote-notification</string>
|
<string>remote-notification</string>
|
||||||
<string>voip</string>
|
<string>voip</string>
|
||||||
</array>
|
</array>
|
||||||
<key>UILaunchStoryboardName</key>
|
<key>UILaunchStoryboardName</key>
|
||||||
<string>LaunchScreen</string>
|
<string>LaunchScreen</string>
|
||||||
<key>UIMainStoryboardFile</key>
|
<key>UIMainStoryboardFile</key>
|
||||||
<string>Main</string>
|
<string>Main</string>
|
||||||
<key>UISupportedInterfaceOrientations</key>
|
<key>UISupportedInterfaceOrientations</key>
|
||||||
<array>
|
<array>
|
||||||
<string>UIInterfaceOrientationPortrait</string>
|
<string>UIInterfaceOrientationPortrait</string>
|
||||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||||
</array>
|
</array>
|
||||||
<key>FlutterDeepLinkingEnabled</key>
|
<key>FlutterDeepLinkingEnabled</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>NSUserActivityTypes</key>
|
<key>NSUserActivityTypes</key>
|
||||||
<array>
|
<array>
|
||||||
<string>INSendMessageIntent</string>
|
<string>INSendMessageIntent</string>
|
||||||
</array>
|
</array>
|
||||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||||
<array>
|
<array>
|
||||||
<string>UIInterfaceOrientationPortrait</string>
|
<string>UIInterfaceOrientationPortrait</string>
|
||||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||||
</array>
|
</array>
|
||||||
</dict>
|
<key>UIStatusBarHidden</key>
|
||||||
|
<false/>
|
||||||
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
@ -1,22 +1,26 @@
|
|||||||
class NetworkPackage {
|
class NetworkPackage {
|
||||||
String method;
|
String method;
|
||||||
|
String? endpoint;
|
||||||
String? message;
|
String? message;
|
||||||
Map<String, dynamic>? payload;
|
Map<String, dynamic>? payload;
|
||||||
|
|
||||||
NetworkPackage({
|
NetworkPackage({
|
||||||
required this.method,
|
required this.method,
|
||||||
|
this.endpoint,
|
||||||
this.message,
|
this.message,
|
||||||
this.payload,
|
this.payload,
|
||||||
});
|
});
|
||||||
|
|
||||||
factory NetworkPackage.fromJson(Map<String, dynamic> json) => NetworkPackage(
|
factory NetworkPackage.fromJson(Map<String, dynamic> json) => NetworkPackage(
|
||||||
method: json['w'],
|
method: json['w'],
|
||||||
|
endpoint: json['e'],
|
||||||
message: json['m'],
|
message: json['m'],
|
||||||
payload: json['p'],
|
payload: json['p'],
|
||||||
);
|
);
|
||||||
|
|
||||||
Map<String, dynamic> toJson() => {
|
Map<String, dynamic> toJson() => {
|
||||||
'w': method,
|
'w': method,
|
||||||
|
'e': endpoint,
|
||||||
'm': message,
|
'm': message,
|
||||||
'p': payload,
|
'p': payload,
|
||||||
};
|
};
|
||||||
|
@ -9,6 +9,7 @@ class LinkExpandController extends GetxController {
|
|||||||
final Map<String, LinkMeta?> _cachedResponse = {};
|
final Map<String, LinkMeta?> _cachedResponse = {};
|
||||||
|
|
||||||
Future<LinkMeta?> expandLink(String url) async {
|
Future<LinkMeta?> expandLink(String url) async {
|
||||||
|
log('[LinkExpander] Expanding link... $url');
|
||||||
final target = utf8.fuse(base64).encode(url);
|
final target = utf8.fuse(base64).encode(url);
|
||||||
if (_cachedResponse.containsKey(target)) return _cachedResponse[target];
|
if (_cachedResponse.containsKey(target)) return _cachedResponse[target];
|
||||||
final client = ServiceFinder.configureClient('dealer');
|
final client = ServiceFinder.configureClient('dealer');
|
||||||
|
@ -88,6 +88,7 @@ class WebSocketProvider extends GetxController {
|
|||||||
websocket?.stream.listen(
|
websocket?.stream.listen(
|
||||||
(event) {
|
(event) {
|
||||||
final packet = NetworkPackage.fromJson(jsonDecode(event));
|
final packet = NetworkPackage.fromJson(jsonDecode(event));
|
||||||
|
log('Websocket incoming message: ${packet.method} ${packet.message}');
|
||||||
stream.sink.add(packet);
|
stream.sink.add(packet);
|
||||||
},
|
},
|
||||||
onDone: () {
|
onDone: () {
|
||||||
@ -148,7 +149,7 @@ class WebSocketProvider extends GetxController {
|
|||||||
'device_token': token,
|
'device_token': token,
|
||||||
'device_id': deviceUuid,
|
'device_id': deviceUuid,
|
||||||
});
|
});
|
||||||
if (resp.statusCode != 200) {
|
if (resp.statusCode != 200 && resp.statusCode != 400) {
|
||||||
throw RequestException(resp);
|
throw RequestException(resp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@ import 'package:solian/widgets/channel/channel_call_indicator.dart';
|
|||||||
import 'package:solian/widgets/chat/call/chat_call_action.dart';
|
import 'package:solian/widgets/chat/call/chat_call_action.dart';
|
||||||
import 'package:solian/widgets/chat/chat_event_list.dart';
|
import 'package:solian/widgets/chat/chat_event_list.dart';
|
||||||
import 'package:solian/widgets/chat/chat_message_input.dart';
|
import 'package:solian/widgets/chat/chat_message_input.dart';
|
||||||
|
import 'package:solian/widgets/chat/chat_typing_indicator.dart';
|
||||||
import 'package:solian/widgets/current_state_action.dart';
|
import 'package:solian/widgets/current_state_action.dart';
|
||||||
|
|
||||||
class ChannelChatScreen extends StatefulWidget {
|
class ChannelChatScreen extends StatefulWidget {
|
||||||
@ -103,12 +104,18 @@ class _ChannelChatScreenState extends State<ChannelChatScreen>
|
|||||||
setState(() => _isBusy = false);
|
setState(() => _isBusy = false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final List<ChannelMember> _typingUsers = List.empty(growable: true);
|
||||||
|
final Map<int, Timer> _typingInactiveTimer = {};
|
||||||
|
|
||||||
void _listenMessages() {
|
void _listenMessages() {
|
||||||
final WebSocketProvider provider = Get.find();
|
final WebSocketProvider ws = Get.find();
|
||||||
_subscription = provider.stream.stream.listen((event) {
|
_subscription = ws.stream.stream.listen((event) {
|
||||||
switch (event.method) {
|
switch (event.method) {
|
||||||
case 'events.new':
|
case 'events.new':
|
||||||
final payload = Event.fromJson(event.payload!);
|
final payload = Event.fromJson(event.payload!);
|
||||||
|
final typingIdx =
|
||||||
|
_typingUsers.indexWhere((x) => x.id == payload.senderId);
|
||||||
|
if (typingIdx != -1) _typingUsers.removeAt(typingIdx);
|
||||||
_chatController.receiveEvent(payload);
|
_chatController.receiveEvent(payload);
|
||||||
break;
|
break;
|
||||||
case 'calls.new':
|
case 'calls.new':
|
||||||
@ -123,6 +130,25 @@ class _ChannelChatScreenState extends State<ChannelChatScreen>
|
|||||||
setState(() => _ongoingCall = null);
|
setState(() => _ongoingCall = null);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'status.typing':
|
||||||
|
if (event.payload?['channel_id'] != _channel!.id) break;
|
||||||
|
final member = ChannelMember.fromJson(event.payload!['member']);
|
||||||
|
if (member.id == _channelProfile!.id) break;
|
||||||
|
if (!_typingUsers.any((x) => x.id == member.id)) {
|
||||||
|
setState(() {
|
||||||
|
_typingUsers.add(member);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
_typingInactiveTimer[member.id]?.cancel();
|
||||||
|
_typingInactiveTimer[member.id] = Timer(
|
||||||
|
const Duration(seconds: 3),
|
||||||
|
() {
|
||||||
|
setState(() {
|
||||||
|
_typingUsers.removeWhere((x) => x.id == member.id);
|
||||||
|
_typingInactiveTimer.remove(member.id);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -280,23 +306,28 @@ class _ChannelChatScreenState extends State<ChannelChatScreen>
|
|||||||
child: BackdropFilter(
|
child: BackdropFilter(
|
||||||
filter: ImageFilter.blur(sigmaX: 50, sigmaY: 50),
|
filter: ImageFilter.blur(sigmaX: 50, sigmaY: 50),
|
||||||
child: SafeArea(
|
child: SafeArea(
|
||||||
child: ChatMessageInput(
|
child: Column(
|
||||||
edit: _messageToEditing,
|
children: [
|
||||||
reply: _messageToReplying,
|
ChatTypingIndicator(users: _typingUsers),
|
||||||
realm: widget.realm,
|
ChatMessageInput(
|
||||||
placeholder: placeholder,
|
edit: _messageToEditing,
|
||||||
channel: _channel!,
|
reply: _messageToReplying,
|
||||||
onSent: (Event item) {
|
realm: widget.realm,
|
||||||
setState(() {
|
placeholder: placeholder,
|
||||||
_chatController.addPendingEvent(item);
|
channel: _channel!,
|
||||||
});
|
onSent: (Event item) {
|
||||||
},
|
setState(() {
|
||||||
onReset: () {
|
_chatController.addPendingEvent(item);
|
||||||
setState(() {
|
});
|
||||||
_messageToReplying = null;
|
},
|
||||||
_messageToEditing = null;
|
onReset: () {
|
||||||
});
|
setState(() {
|
||||||
},
|
_messageToReplying = null;
|
||||||
|
_messageToEditing = null;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -329,6 +360,9 @@ class _ChannelChatScreenState extends State<ChannelChatScreen>
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
|
for (var timer in _typingInactiveTimer.values) {
|
||||||
|
timer.cancel();
|
||||||
|
}
|
||||||
_subscription?.cancel();
|
_subscription?.cancel();
|
||||||
WidgetsBinding.instance.removeObserver(this);
|
WidgetsBinding.instance.removeObserver(this);
|
||||||
super.dispose();
|
super.dispose();
|
||||||
|
@ -385,4 +385,5 @@ const i18nEnglish = {
|
|||||||
'unknown': 'Unknown',
|
'unknown': 'Unknown',
|
||||||
'collapse': 'Collapse',
|
'collapse': 'Collapse',
|
||||||
'expand': 'Expand',
|
'expand': 'Expand',
|
||||||
|
'typingMessage': '@user are typing...',
|
||||||
};
|
};
|
||||||
|
@ -355,4 +355,5 @@ const i18nSimplifiedChinese = {
|
|||||||
'unknown': '未知',
|
'unknown': '未知',
|
||||||
'collapse': '折叠',
|
'collapse': '折叠',
|
||||||
'expand': '展开',
|
'expand': '展开',
|
||||||
|
'typingMessage': '@user 正在输入中…',
|
||||||
};
|
};
|
||||||
|
@ -147,17 +147,21 @@ class _AttachmentItemImage extends StatelessWidget {
|
|||||||
errorWidget: (context, url, error) {
|
errorWidget: (context, url, error) {
|
||||||
return Material(
|
return Material(
|
||||||
color: Theme.of(context).colorScheme.surface,
|
color: Theme.of(context).colorScheme.surface,
|
||||||
child: Center(
|
child: Column(
|
||||||
child: const Icon(Icons.close, size: 32)
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
.animate(onPlay: (e) => e.repeat(reverse: true))
|
children: [
|
||||||
.fade(duration: 500.ms),
|
const Icon(Icons.close, size: 32)
|
||||||
|
.animate(onPlay: (e) => e.repeat(reverse: true))
|
||||||
|
.fade(duration: 500.ms),
|
||||||
|
Text(error.toString()),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
else
|
else
|
||||||
Image.network(
|
Image.network(
|
||||||
ServiceFinder.buildUrl('files', '/attachments/${item.id}'),
|
ServiceFinder.buildUrl('files', '/attachments/${item.rid}'),
|
||||||
fit: fit,
|
fit: fit,
|
||||||
loadingBuilder: (BuildContext context, Widget child,
|
loadingBuilder: (BuildContext context, Widget child,
|
||||||
ImageChunkEvent? loadingProgress) {
|
ImageChunkEvent? loadingProgress) {
|
||||||
@ -174,10 +178,14 @@ class _AttachmentItemImage extends StatelessWidget {
|
|||||||
errorBuilder: (context, error, stackTrace) {
|
errorBuilder: (context, error, stackTrace) {
|
||||||
return Material(
|
return Material(
|
||||||
color: Theme.of(context).colorScheme.surface,
|
color: Theme.of(context).colorScheme.surface,
|
||||||
child: Center(
|
child: Column(
|
||||||
child: const Icon(Icons.close, size: 32)
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
.animate(onPlay: (e) => e.repeat(reverse: true))
|
children: [
|
||||||
.fade(duration: 500.ms),
|
const Icon(Icons.close, size: 32)
|
||||||
|
.animate(onPlay: (e) => e.repeat(reverse: true))
|
||||||
|
.fade(duration: 500.ms),
|
||||||
|
Text(error.toString()),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -132,6 +132,9 @@ class _AttachmentListState extends State<AttachmentList> {
|
|||||||
_getMetadataList();
|
_getMetadataList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Color get _unFocusColor =>
|
||||||
|
Theme.of(context).colorScheme.onSurface.withOpacity(0.75);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
if (widget.attachmentsId.isEmpty) {
|
if (widget.attachmentsId.isEmpty) {
|
||||||
@ -139,12 +142,24 @@ class _AttachmentListState extends State<AttachmentList> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (_isLoading) {
|
if (_isLoading) {
|
||||||
return Container(
|
return Row(
|
||||||
decoration: BoxDecoration(
|
children: [
|
||||||
color: Theme.of(context).colorScheme.surfaceContainerHigh,
|
Icon(
|
||||||
),
|
Icons.file_copy,
|
||||||
child: const LinearProgressIndicator(),
|
size: 12,
|
||||||
);
|
color: _unFocusColor,
|
||||||
|
).paddingOnly(right: 5),
|
||||||
|
Text(
|
||||||
|
'attachmentHint'.trParams(
|
||||||
|
{'count': widget.attachmentsId.length.toString()},
|
||||||
|
),
|
||||||
|
style: TextStyle(color: _unFocusColor, fontSize: 12),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
.paddingSymmetric(horizontal: 8)
|
||||||
|
.animate(onPlay: (c) => c.repeat(reverse: true))
|
||||||
|
.fadeIn(duration: 1250.ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (widget.isColumn) {
|
if (widget.isColumn) {
|
||||||
@ -159,6 +174,9 @@ class _AttachmentListState extends State<AttachmentList> {
|
|||||||
if (element == null) return const SizedBox();
|
if (element == null) return const SizedBox();
|
||||||
double ratio = element.metadata?['ratio']?.toDouble() ?? 16 / 9;
|
double ratio = element.metadata?['ratio']?.toDouble() ?? 16 / 9;
|
||||||
return Container(
|
return Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Theme.of(context).colorScheme.surfaceContainerHigh,
|
||||||
|
),
|
||||||
constraints: BoxConstraints(
|
constraints: BoxConstraints(
|
||||||
maxWidth: widget.columnMaxWidth,
|
maxWidth: widget.columnMaxWidth,
|
||||||
maxHeight: 640,
|
maxHeight: 640,
|
||||||
@ -204,6 +222,7 @@ class _AttachmentListState extends State<AttachmentList> {
|
|||||||
final element = _attachmentsMeta[idx];
|
final element = _attachmentsMeta[idx];
|
||||||
return Container(
|
return Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
|
color: Theme.of(context).colorScheme.surfaceContainerHigh,
|
||||||
border: Border.all(
|
border: Border.all(
|
||||||
color: Theme.of(context).dividerColor,
|
color: Theme.of(context).dividerColor,
|
||||||
width: 1,
|
width: 1,
|
||||||
|
@ -197,8 +197,11 @@ class ChatEvent extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
).paddingOnly(right: 12),
|
).paddingOnly(right: 12),
|
||||||
|
if (!isContentPreviewing)
|
||||||
|
_buildLinkExpansion().paddingOnly(left: 52, right: 8),
|
||||||
_buildAttachment(context, isMinimal: isContentPreviewing).paddingOnly(
|
_buildAttachment(context, isMinimal: isContentPreviewing).paddingOnly(
|
||||||
left: isContentPreviewing ? 12 : 56,
|
left: isContentPreviewing ? 12 : 56,
|
||||||
|
right: 8,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:cached_network_image/cached_network_image.dart';
|
import 'package:cached_network_image/cached_network_image.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_typeahead/flutter_typeahead.dart';
|
import 'package:flutter_typeahead/flutter_typeahead.dart';
|
||||||
@ -7,10 +10,12 @@ import 'package:solian/exts.dart';
|
|||||||
import 'package:solian/models/account.dart';
|
import 'package:solian/models/account.dart';
|
||||||
import 'package:solian/models/channel.dart';
|
import 'package:solian/models/channel.dart';
|
||||||
import 'package:solian/models/event.dart';
|
import 'package:solian/models/event.dart';
|
||||||
|
import 'package:solian/models/packet.dart';
|
||||||
import 'package:solian/platform.dart';
|
import 'package:solian/platform.dart';
|
||||||
import 'package:solian/providers/attachment_uploader.dart';
|
import 'package:solian/providers/attachment_uploader.dart';
|
||||||
import 'package:solian/providers/auth.dart';
|
import 'package:solian/providers/auth.dart';
|
||||||
import 'package:solian/providers/stickers.dart';
|
import 'package:solian/providers/stickers.dart';
|
||||||
|
import 'package:solian/providers/websocket.dart';
|
||||||
import 'package:solian/widgets/account/account_avatar.dart';
|
import 'package:solian/widgets/account/account_avatar.dart';
|
||||||
import 'package:solian/widgets/attachments/attachment_editor.dart';
|
import 'package:solian/widgets/attachments/attachment_editor.dart';
|
||||||
import 'package:solian/widgets/chat/chat_event.dart';
|
import 'package:solian/widgets/chat/chat_event.dart';
|
||||||
@ -196,6 +201,36 @@ class _ChatMessageInputState extends State<ChatMessageInput> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Timer? _typingNotifyTimer;
|
||||||
|
bool _typingStatus = false;
|
||||||
|
|
||||||
|
Future<void> _sendTypingStatus() async {
|
||||||
|
final WebSocketProvider ws = Get.find();
|
||||||
|
ws.websocket?.sink.add(jsonEncode(
|
||||||
|
NetworkPackage(
|
||||||
|
method: 'status.typing',
|
||||||
|
endpoint: 'messaging',
|
||||||
|
payload: {
|
||||||
|
'channel_id': widget.channel.id,
|
||||||
|
},
|
||||||
|
).toJson(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
void _pingEnterMessageStatus() {
|
||||||
|
if (!_typingStatus) {
|
||||||
|
_sendTypingStatus();
|
||||||
|
_typingStatus = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_typingNotifyTimer == null || !_typingNotifyTimer!.isActive) {
|
||||||
|
_typingNotifyTimer?.cancel();
|
||||||
|
_typingNotifyTimer = Timer(const Duration(milliseconds: 1850), () {
|
||||||
|
_typingStatus = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void _resetInput() {
|
void _resetInput() {
|
||||||
if (widget.onReset != null) widget.onReset!();
|
if (widget.onReset != null) widget.onReset!();
|
||||||
_editTo = null;
|
_editTo = null;
|
||||||
@ -269,6 +304,20 @@ class _ChatMessageInputState extends State<ChatMessageInput> {
|
|||||||
super.didUpdateWidget(oldWidget);
|
super.didUpdateWidget(oldWidget);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_textController.addListener(_pingEnterMessageStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_textController.removeListener(_pingEnterMessageStatus);
|
||||||
|
_textController.dispose();
|
||||||
|
_typingNotifyTimer?.cancel();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final notifyBannerActions = [
|
final notifyBannerActions = [
|
||||||
|
58
lib/widgets/chat/chat_typing_indicator.dart
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
import 'package:solian/models/channel.dart';
|
||||||
|
|
||||||
|
class ChatTypingIndicator extends StatefulWidget {
|
||||||
|
final List<ChannelMember> users;
|
||||||
|
|
||||||
|
const ChatTypingIndicator({super.key, required this.users});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<ChatTypingIndicator> createState() => _ChatTypingIndicatorState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ChatTypingIndicatorState extends State<ChatTypingIndicator>
|
||||||
|
with SingleTickerProviderStateMixin {
|
||||||
|
late final AnimationController _controller = AnimationController(
|
||||||
|
duration: const Duration(milliseconds: 250),
|
||||||
|
vsync: this,
|
||||||
|
);
|
||||||
|
late final Animation<double> _animation = CurvedAnimation(
|
||||||
|
parent: _controller,
|
||||||
|
curve: Curves.easeInOut,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_controller.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didUpdateWidget(covariant ChatTypingIndicator oldWidget) {
|
||||||
|
if (widget.users.isNotEmpty) {
|
||||||
|
_controller.animateTo(1);
|
||||||
|
} else {
|
||||||
|
_controller.animateTo(0);
|
||||||
|
}
|
||||||
|
super.didUpdateWidget(oldWidget);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return SizeTransition(
|
||||||
|
sizeFactor: _animation,
|
||||||
|
axis: Axis.vertical,
|
||||||
|
axisAlignment: -1,
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
const Icon(Icons.more_horiz),
|
||||||
|
const SizedBox(width: 6),
|
||||||
|
Text('typingMessage'.trParams({
|
||||||
|
'user': widget.users.map((x) => x.account.nick).join(', '),
|
||||||
|
})),
|
||||||
|
],
|
||||||
|
).paddingSymmetric(horizontal: 16),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
import 'package:cached_network_image/cached_network_image.dart';
|
import 'package:cached_network_image/cached_network_image.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_animate/flutter_animate.dart';
|
||||||
import 'package:flutter_markdown/flutter_markdown.dart';
|
import 'package:flutter_markdown/flutter_markdown.dart';
|
||||||
import 'package:flutter_svg/svg.dart';
|
import 'package:flutter_svg/svg.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
@ -17,8 +18,36 @@ class LinkExpansion extends StatelessWidget {
|
|||||||
return SvgPicture.network(url, width: width, height: height);
|
return SvgPicture.network(url, width: width, height: height);
|
||||||
}
|
}
|
||||||
return PlatformInfo.canCacheImage
|
return PlatformInfo.canCacheImage
|
||||||
? CachedNetworkImage(imageUrl: url, width: width, height: height)
|
? CachedNetworkImage(
|
||||||
: Image.network(url, width: width, height: height);
|
imageUrl: url,
|
||||||
|
width: width,
|
||||||
|
height: height,
|
||||||
|
errorWidget: (context, url, error) {
|
||||||
|
return Material(
|
||||||
|
color: Theme.of(context).colorScheme.surface,
|
||||||
|
child: Center(
|
||||||
|
child: const Icon(Icons.close, size: 32)
|
||||||
|
.animate(onPlay: (e) => e.repeat(reverse: true))
|
||||||
|
.fade(duration: 500.ms),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
)
|
||||||
|
: Image.network(
|
||||||
|
url,
|
||||||
|
width: width,
|
||||||
|
height: height,
|
||||||
|
errorBuilder: (context, error, stackTrace) {
|
||||||
|
return Material(
|
||||||
|
color: Theme.of(context).colorScheme.surface,
|
||||||
|
child: Center(
|
||||||
|
child: const Icon(Icons.close, size: 32)
|
||||||
|
.animate(onPlay: (e) => e.repeat(reverse: true))
|
||||||
|
.fade(duration: 500.ms),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -197,10 +197,7 @@ class _AppNavigationDrawerState extends State<AppNavigationDrawer>
|
|||||||
} else if (SolianTheme.isLargeScreen(context)) {
|
} else if (SolianTheme.isLargeScreen(context)) {
|
||||||
_collapseDrawer();
|
_collapseDrawer();
|
||||||
} else {
|
} else {
|
||||||
_drawerAnimationController.animateTo(
|
_drawerAnimationController.value = 1;
|
||||||
1,
|
|
||||||
duration: const Duration(milliseconds: 100),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
90
pubspec.lock
@ -38,6 +38,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.11"
|
version: "2.0.11"
|
||||||
|
ansicolor:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: ansicolor
|
||||||
|
sha256: "50e982d500bc863e1d703448afdbf9e5a72eb48840a4f766fa361ffd6877055f"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.3"
|
||||||
archive:
|
archive:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -278,6 +286,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.5"
|
version: "3.0.5"
|
||||||
|
csslib:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: csslib
|
||||||
|
sha256: "706b5707578e0c1b4b7550f64078f0a0f19dec3f50a178ffae7006b0a9ca58fb"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.0"
|
||||||
cupertino_icons:
|
cupertino_icons:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -715,14 +731,22 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.6.17+1"
|
version: "0.6.17+1"
|
||||||
|
flutter_native_splash:
|
||||||
|
dependency: "direct dev"
|
||||||
|
description:
|
||||||
|
name: flutter_native_splash
|
||||||
|
sha256: aa06fec78de2190f3db4319dd60fdc8d12b2626e93ef9828633928c2dcaea840
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.4.1"
|
||||||
flutter_plugin_android_lifecycle:
|
flutter_plugin_android_lifecycle:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: flutter_plugin_android_lifecycle
|
name: flutter_plugin_android_lifecycle
|
||||||
sha256: "9d98bd47ef9d34e803d438f17fd32b116d31009f534a6fa5ce3a1167f189a6de"
|
sha256: "9ee02950848f61c4129af3d6ec84a1cfc0e47931abc746b03e7a3bc3e8ff6eda"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.21"
|
version: "2.0.22"
|
||||||
flutter_secure_storage:
|
flutter_secure_storage:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -865,10 +889,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: go_router
|
name: go_router
|
||||||
sha256: ddc16d34b0d74cb313986918c0f0885a7ba2fc24d8fb8419de75f0015144ccfe
|
sha256: "2ddb88e9ad56ae15ee144ed10e33886777eb5ca2509a914850a5faa7b52ff459"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "14.2.3"
|
version: "14.2.7"
|
||||||
graphs:
|
graphs:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -885,6 +909,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.5"
|
version: "1.0.5"
|
||||||
|
html:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: html
|
||||||
|
sha256: "3a7812d5bcd2894edf53dfaf8cd640876cf6cef50a8f238745c8b8120ea74d3a"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.15.4"
|
||||||
http:
|
http:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -953,10 +985,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: image_picker_android
|
name: image_picker_android
|
||||||
sha256: "8c5abf0dcc24fe6e8e0b4a5c0b51a5cf30cefdf6407a3213dae61edc75a70f56"
|
sha256: c0a6763d50b354793d0192afd0a12560b823147d3ded7c6b77daf658fa05cc85
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.8.12+12"
|
version: "0.8.12+13"
|
||||||
image_picker_for_web:
|
image_picker_for_web:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1153,10 +1185,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: media_kit
|
name: media_kit
|
||||||
sha256: "3289062540e3b8b9746e5c50d95bd78a9289826b7227e253dff806d002b9e67a"
|
sha256: "1f1deee148533d75129a6f38251ff8388e33ee05fc2d20a6a80e57d6051b7b62"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.10+1"
|
version: "1.1.11"
|
||||||
media_kit_libs_android_video:
|
media_kit_libs_android_video:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1193,34 +1225,34 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: media_kit_libs_video
|
name: media_kit_libs_video
|
||||||
sha256: "3688e0c31482074578652bf038ce6301a5d21e1eda6b54fc3117ffeb4bdba067"
|
sha256: "20bb4aefa8fece282b59580e1cd8528117297083a6640c98c2e98cfc96b93288"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.4"
|
version: "1.0.5"
|
||||||
media_kit_libs_windows_video:
|
media_kit_libs_windows_video:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: media_kit_libs_windows_video
|
name: media_kit_libs_windows_video
|
||||||
sha256: "7bace5f35d9afcc7f9b5cdadb7541d2191a66bb3fc71bfa11c1395b3360f6122"
|
sha256: "32654572167825c42c55466f5d08eee23ea11061c84aa91b09d0e0f69bdd0887"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.9"
|
version: "1.0.10"
|
||||||
media_kit_native_event_loop:
|
media_kit_native_event_loop:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: media_kit_native_event_loop
|
name: media_kit_native_event_loop
|
||||||
sha256: a605cf185499d14d58935b8784955a92a4bf0ff4e19a23de3d17a9106303930e
|
sha256: "7d82e3b3e9ded5c35c3146c5ba1da3118d1dd8ac3435bac7f29f458181471b40"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.8"
|
version: "1.0.9"
|
||||||
media_kit_video:
|
media_kit_video:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: media_kit_video
|
name: media_kit_video
|
||||||
sha256: c048d11a19e379aebbe810647636e3fc6d18374637e2ae12def4ff8a4b99a882
|
sha256: "2cc3b966679963ba25a4ce5b771e532a521ebde7c6aa20e9802bec95d9916c8f"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.4"
|
version: "1.2.5"
|
||||||
meta:
|
meta:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1385,10 +1417,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: permission_handler_html
|
name: permission_handler_html
|
||||||
sha256: d220eb8476b466d58b161e10b3001d93999010a26228a3fb89c4280db1249546
|
sha256: af26edbbb1f2674af65a8f4b56e1a6f526156bc273d0e65dd8075fab51c78851
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.1.3+1"
|
version: "0.1.3+2"
|
||||||
permission_handler_platform_interface:
|
permission_handler_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1481,10 +1513,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: process_run
|
name: process_run
|
||||||
sha256: c917dfb5f7afad4c7485bc00a4df038621248fce046105020cea276d1a87c820
|
sha256: "112a77da35be50617ed9e2230df68d0817972f225e7f97ce8336f76b4e601606"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.0"
|
version: "1.2.0"
|
||||||
protobuf:
|
protobuf:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1665,10 +1697,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: shared_preferences_android
|
name: shared_preferences_android
|
||||||
sha256: a7e8467e9181cef109f601e3f65765685786c1a738a83d7fbbde377589c0d974
|
sha256: "480ba4345773f56acda9abf5f50bd966f581dac5d514e5fc4a18c62976bbba7e"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.3.1"
|
version: "2.3.2"
|
||||||
shared_preferences_foundation:
|
shared_preferences_foundation:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1906,6 +1938,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.3.1"
|
version: "0.3.1"
|
||||||
|
universal_io:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: universal_io
|
||||||
|
sha256: "1722b2dcc462b4b2f3ee7d188dad008b6eb4c40bbd03a3de451d82c78bba9aad"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.2.2"
|
||||||
universal_platform:
|
universal_platform:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1934,10 +1974,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: url_launcher_android
|
name: url_launcher_android
|
||||||
sha256: f0c73347dfcfa5b3db8bc06e1502668265d39c08f310c29bff4e28eea9699f79
|
sha256: e35a698ac302dd68e41f73250bd9517fe3ab5fa4f18fe4647a0872db61bacbab
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.3.9"
|
version: "6.3.10"
|
||||||
url_launcher_ios:
|
url_launcher_ios:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -2140,4 +2180,4 @@ packages:
|
|||||||
version: "3.1.2"
|
version: "3.1.2"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=3.5.0 <4.0.0"
|
dart: ">=3.5.0 <4.0.0"
|
||||||
flutter: ">=3.22.0"
|
flutter: ">=3.24.0"
|
||||||
|
10
pubspec.yaml
@ -2,7 +2,7 @@ name: solian
|
|||||||
description: "The Solar Network App"
|
description: "The Solar Network App"
|
||||||
publish_to: "none"
|
publish_to: "none"
|
||||||
|
|
||||||
version: 1.2.1+22
|
version: 1.2.1+24
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=3.3.4 <4.0.0"
|
sdk: ">=3.3.4 <4.0.0"
|
||||||
@ -85,6 +85,7 @@ dev_dependencies:
|
|||||||
build_runner: ^2.1.2
|
build_runner: ^2.1.2
|
||||||
sqflite_common_ffi: ^2.3.3
|
sqflite_common_ffi: ^2.3.3
|
||||||
sqflite_common_ffi_web: ^0.4.3+1
|
sqflite_common_ffi_web: ^0.4.3+1
|
||||||
|
flutter_native_splash: ^2.4.1
|
||||||
|
|
||||||
flutter:
|
flutter:
|
||||||
uses-material-design: true
|
uses-material-design: true
|
||||||
@ -128,7 +129,7 @@ flutter_launcher_icons:
|
|||||||
generate: true
|
generate: true
|
||||||
image_path: "assets/icon-w-shadow.png"
|
image_path: "assets/icon-w-shadow.png"
|
||||||
background_color: "#ffffff"
|
background_color: "#ffffff"
|
||||||
theme_color: "#4b5094"
|
theme_color: "#92645d"
|
||||||
windows:
|
windows:
|
||||||
generate: true
|
generate: true
|
||||||
image_path: "assets/icon-w-shadow.png"
|
image_path: "assets/icon-w-shadow.png"
|
||||||
@ -137,5 +138,10 @@ flutter_launcher_icons:
|
|||||||
generate: true
|
generate: true
|
||||||
image_path: "assets/icon-w-shadow.png"
|
image_path: "assets/icon-w-shadow.png"
|
||||||
|
|
||||||
|
flutter_native_splash:
|
||||||
|
color: "#fef8f7"
|
||||||
|
color_dark: "#191110"
|
||||||
|
image: assets/icon-w-shadow.png
|
||||||
|
|
||||||
msix_config:
|
msix_config:
|
||||||
protocol_activation: solink
|
protocol_activation: solink
|
||||||
|
115
web/index.html
@ -1,6 +1,4 @@
|
|||||||
<!doctype html>
|
<!DOCTYPE html><html><head>
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<!--
|
<!--
|
||||||
If you are serving your web app in a path other than the root, change the
|
If you are serving your web app in a path other than the root, change the
|
||||||
href value below to reflect the base path you are serving from.
|
href value below to reflect the base path you are serving from.
|
||||||
@ -14,24 +12,24 @@
|
|||||||
This is a placeholder for base href that will be replaced by the value of
|
This is a placeholder for base href that will be replaced by the value of
|
||||||
the `--base-href` argument provided to `flutter build`.
|
the `--base-href` argument provided to `flutter build`.
|
||||||
-->
|
-->
|
||||||
<base href="$FLUTTER_BASE_HREF" />
|
<base href="$FLUTTER_BASE_HREF">
|
||||||
|
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8">
|
||||||
<meta content="IE=Edge" http-equiv="X-UA-Compatible" />
|
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
|
||||||
<meta name="description" content="A new Flutter project." />
|
<meta name="description" content="A new Flutter project.">
|
||||||
|
|
||||||
<!-- iOS meta tags & icons -->
|
<!-- iOS meta tags & icons -->
|
||||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||||
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
|
<meta name="apple-mobile-web-app-status-bar-style" content="black">
|
||||||
<meta name="apple-mobile-web-app-title" content="solian" />
|
<meta name="apple-mobile-web-app-title" content="solian">
|
||||||
<link rel="apple-touch-icon" href="icons/Icon-192.png" />
|
<link rel="apple-touch-icon" href="icons/Icon-192.png">
|
||||||
|
|
||||||
<!-- Cropper.js -->
|
<!-- Cropper.js -->
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.6.2/cropper.css" />
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.6.2/cropper.css">
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.6.2/cropper.min.js"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.6.2/cropper.min.js"></script>
|
||||||
|
|
||||||
<!-- Favicon -->
|
<!-- Favicon -->
|
||||||
<link rel="icon" type="image/png" href="favicon.png" />
|
<link rel="icon" type="image/png" href="favicon.png">
|
||||||
|
|
||||||
<!-- Loading styles -->
|
<!-- Loading styles -->
|
||||||
<style>
|
<style>
|
||||||
@ -68,14 +66,95 @@
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<title>Solian</title>
|
<title>Solian</title>
|
||||||
<link rel="manifest" href="manifest.json" />
|
<link rel="manifest" href="manifest.json">
|
||||||
</head>
|
|
||||||
|
|
||||||
|
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport">
|
||||||
|
<style id="splash-screen-style">
|
||||||
|
html {
|
||||||
|
height: 100%
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
min-height: 100%;
|
||||||
|
background-color: #fef8f7;
|
||||||
|
background-size: 100% 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.center {
|
||||||
|
margin: 0;
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
-ms-transform: translate(-50%, -50%);
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.contain {
|
||||||
|
display:block;
|
||||||
|
width:100%; height:100%;
|
||||||
|
object-fit: contain;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stretch {
|
||||||
|
display:block;
|
||||||
|
width:100%; height:100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cover {
|
||||||
|
display:block;
|
||||||
|
width:100%; height:100%;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottom {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 50%;
|
||||||
|
-ms-transform: translate(-50%, 0);
|
||||||
|
transform: translate(-50%, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottomLeft {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottomRight {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
body {
|
||||||
|
background-color: #191110;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script id="splash-screen-script">
|
||||||
|
function removeSplashFromWeb() {
|
||||||
|
document.getElementById("splash")?.remove();
|
||||||
|
document.getElementById("splash-branding")?.remove();
|
||||||
|
document.body.style.background = "transparent";
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
<picture id="splash">
|
||||||
|
<source srcset="splash/img/light-1x.png 1x, splash/img/light-2x.png 2x, splash/img/light-3x.png 3x, splash/img/light-4x.png 4x" media="(prefers-color-scheme: light)">
|
||||||
|
<source srcset="splash/img/dark-1x.png 1x, splash/img/dark-2x.png 2x, splash/img/dark-3x.png 3x, splash/img/dark-4x.png 4x" media="(prefers-color-scheme: dark)">
|
||||||
|
<img class="center" aria-hidden="true" src="splash/img/light-1x.png" alt="">
|
||||||
|
</picture>
|
||||||
|
|
||||||
<div class="loader-container">
|
<div class="loader-container">
|
||||||
<div class="loader"></div>
|
<div class="loader"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="flutter_bootstrap.js" async></script>
|
<script src="flutter_bootstrap.js" async=""></script>
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
</body></html>
|
BIN
web/splash/img/dark-1x.png
Normal file
After Width: | Height: | Size: 39 KiB |
BIN
web/splash/img/dark-2x.png
Normal file
After Width: | Height: | Size: 117 KiB |
BIN
web/splash/img/dark-3x.png
Normal file
After Width: | Height: | Size: 233 KiB |
BIN
web/splash/img/dark-4x.png
Normal file
After Width: | Height: | Size: 355 KiB |
BIN
web/splash/img/light-1x.png
Normal file
After Width: | Height: | Size: 39 KiB |
BIN
web/splash/img/light-2x.png
Normal file
After Width: | Height: | Size: 117 KiB |
BIN
web/splash/img/light-3x.png
Normal file
After Width: | Height: | Size: 233 KiB |
BIN
web/splash/img/light-4x.png
Normal file
After Width: | Height: | Size: 355 KiB |