├── linux
├── .gitignore
├── main.cc
├── flutter
│ ├── generated_plugin_registrant.cc
│ ├── generated_plugin_registrant.h
│ ├── generated_plugins.cmake
│ └── CMakeLists.txt
├── my_application.h
├── my_application.cc
└── CMakeLists.txt
├── ios
├── Flutter
│ ├── Debug.xcconfig
│ ├── Release.xcconfig
│ └── AppFrameworkInfo.plist
├── Runner
│ ├── Runner-Bridging-Header.h
│ ├── Assets.xcassets
│ │ ├── LaunchImage.imageset
│ │ │ ├── LaunchImage.png
│ │ │ ├── LaunchImage@2x.png
│ │ │ ├── LaunchImage@3x.png
│ │ │ ├── README.md
│ │ │ └── Contents.json
│ │ └── AppIcon.appiconset
│ │ │ ├── Icon-App-20x20@1x.png
│ │ │ ├── Icon-App-20x20@2x.png
│ │ │ ├── Icon-App-20x20@3x.png
│ │ │ ├── Icon-App-29x29@1x.png
│ │ │ ├── Icon-App-29x29@2x.png
│ │ │ ├── Icon-App-29x29@3x.png
│ │ │ ├── Icon-App-40x40@1x.png
│ │ │ ├── Icon-App-40x40@2x.png
│ │ │ ├── Icon-App-40x40@3x.png
│ │ │ ├── Icon-App-60x60@2x.png
│ │ │ ├── Icon-App-60x60@3x.png
│ │ │ ├── Icon-App-76x76@1x.png
│ │ │ ├── Icon-App-76x76@2x.png
│ │ │ ├── Icon-App-1024x1024@1x.png
│ │ │ ├── Icon-App-83.5x83.5@2x.png
│ │ │ └── Contents.json
│ ├── AppDelegate.swift
│ ├── GoogleService-Info.plist
│ ├── Base.lproj
│ │ ├── Main.storyboard
│ │ └── LaunchScreen.storyboard
│ └── Info.plist
├── Runner.xcodeproj
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ ├── WorkspaceSettings.xcsettings
│ │ │ └── IDEWorkspaceChecks.plist
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── Runner.xcscheme
├── Runner.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ ├── WorkspaceSettings.xcsettings
│ │ └── IDEWorkspaceChecks.plist
├── firebase_app_id_file.json
└── .gitignore
├── .fvm
└── fvm_config.json
├── extras
├── f_b.jpg
├── bottom_bar.png
└── screenshot
│ ├── 1.png
│ ├── 2.png
│ ├── 3.png
│ ├── 4.png
│ └── 5.png
├── macos
├── Flutter
│ ├── Flutter-Debug.xcconfig
│ ├── Flutter-Release.xcconfig
│ └── GeneratedPluginRegistrant.swift
├── Runner
│ ├── Configs
│ │ ├── Debug.xcconfig
│ │ ├── Release.xcconfig
│ │ ├── Warnings.xcconfig
│ │ └── AppInfo.xcconfig
│ ├── Assets.xcassets
│ │ └── AppIcon.appiconset
│ │ │ ├── app_icon_128.png
│ │ │ ├── app_icon_16.png
│ │ │ ├── app_icon_256.png
│ │ │ ├── app_icon_32.png
│ │ │ ├── app_icon_512.png
│ │ │ ├── app_icon_64.png
│ │ │ ├── app_icon_1024.png
│ │ │ └── Contents.json
│ ├── AppDelegate.swift
│ ├── Release.entitlements
│ ├── DebugProfile.entitlements
│ ├── MainFlutterWindow.swift
│ ├── Info.plist
│ └── GoogleService-Info.plist
├── .gitignore
├── Runner.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
├── firebase_app_id_file.json
└── Runner.xcodeproj
│ ├── project.xcworkspace
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
│ └── xcshareddata
│ └── xcschemes
│ └── Runner.xcscheme
├── assets
├── icon.png
├── logo.png
└── lottie
│ └── loading.json
├── web
├── favicon.png
├── icons
│ ├── Icon-192.png
│ ├── Icon-512.png
│ ├── Icon-maskable-192.png
│ └── Icon-maskable-512.png
├── manifest.json
└── index.html
├── android
├── gradle.properties
├── app
│ ├── src
│ │ ├── main
│ │ │ ├── ic_launcher-playstore.png
│ │ │ ├── res
│ │ │ │ ├── mipmap-hdpi
│ │ │ │ │ ├── ic_music.png
│ │ │ │ │ ├── ic_launcher_round.png
│ │ │ │ │ ├── ic_launcher_background.png
│ │ │ │ │ └── ic_launcher_foreground.png
│ │ │ │ ├── mipmap-mdpi
│ │ │ │ │ ├── ic_music.png
│ │ │ │ │ ├── ic_launcher_round.png
│ │ │ │ │ ├── ic_launcher_background.png
│ │ │ │ │ └── ic_launcher_foreground.png
│ │ │ │ ├── mipmap-xhdpi
│ │ │ │ │ ├── ic_music.png
│ │ │ │ │ ├── ic_launcher_round.png
│ │ │ │ │ ├── ic_launcher_background.png
│ │ │ │ │ └── ic_launcher_foreground.png
│ │ │ │ ├── mipmap-xxhdpi
│ │ │ │ │ ├── ic_music.png
│ │ │ │ │ ├── ic_launcher_round.png
│ │ │ │ │ ├── ic_launcher_background.png
│ │ │ │ │ └── ic_launcher_foreground.png
│ │ │ │ ├── mipmap-xxxhdpi
│ │ │ │ │ ├── ic_music.png
│ │ │ │ │ ├── ic_launcher_round.png
│ │ │ │ │ ├── ic_launcher_background.png
│ │ │ │ │ └── ic_launcher_foreground.png
│ │ │ │ ├── mipmap-anydpi-v26
│ │ │ │ │ ├── ic_launcher.xml
│ │ │ │ │ └── ic_launcher_round.xml
│ │ │ │ ├── drawable
│ │ │ │ │ └── launch_background.xml
│ │ │ │ ├── drawable-v21
│ │ │ │ │ └── launch_background.xml
│ │ │ │ ├── values
│ │ │ │ │ └── styles.xml
│ │ │ │ └── values-night
│ │ │ │ │ └── styles.xml
│ │ │ ├── kotlin
│ │ │ │ └── com
│ │ │ │ │ └── example
│ │ │ │ │ └── sunday_suspense
│ │ │ │ │ └── MainActivity.kt
│ │ │ └── AndroidManifest.xml
│ │ ├── debug
│ │ │ └── AndroidManifest.xml
│ │ └── profile
│ │ │ └── AndroidManifest.xml
│ ├── google-services.json
│ └── build.gradle
├── gradle
│ └── wrapper
│ │ └── gradle-wrapper.properties
├── .gitignore
├── settings.gradle
└── build.gradle
├── .vscode
├── settings.json
└── launch.json
├── server
├── requirements.txt
├── backup.py
├── checkup_db.py
├── checkplaylist.py
├── main.py
└── build_new_item.py
├── .github
├── ISSUE_TEMPLATE
│ ├── custom.md
│ ├── feature_request.md
│ └── bug_report.md
├── workflows
│ ├── issuenotifier.yml
│ ├── update_db.yml
│ ├── prchecker.yml
│ └── db_backup.yml
└── FUNDING.yml
├── lib
├── screens
│ ├── aboutpage.dart
│ ├── historypage.dart
│ ├── root.dart
│ ├── show_all_page.dart
│ ├── searchScreen.dart
│ ├── homepage.dart
│ ├── categorypage.dart
│ └── player.dart
├── notifiers
│ ├── play_button_notifier.dart
│ ├── repeat_button_notifier.dart
│ └── progress_notifier.dart
├── utils.dart
├── services
│ ├── service_locator.dart
│ ├── database_service.dart
│ ├── database_service.txt
│ └── notification_service.dart
├── generated_plugin_registrant.dart
├── widgets
│ ├── searchbar.dart
│ ├── miniplayer.dart
│ └── art_glass_overlay.dart
├── ui
│ ├── app_colors.dart
│ ├── text_styles.dart
│ └── my_theme.dart
├── main.dart
├── firebase_options.dart
└── page_manager.dart
├── .gitignore
├── test
└── widget_test.dart
├── pubspec.yaml
├── analysis_options.yaml
├── .metadata
├── CONTRIBUTING.md
├── README.md
└── CODE_OF_CONDUCT.md
/linux/.gitignore:
--------------------------------------------------------------------------------
1 | flutter/ephemeral
2 |
--------------------------------------------------------------------------------
/ios/Flutter/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/ios/Runner/Runner-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import "GeneratedPluginRegistrant.h"
2 |
--------------------------------------------------------------------------------
/.fvm/fvm_config.json:
--------------------------------------------------------------------------------
1 | {
2 | "flutterSdkVersion": "stable",
3 | "flavors": {}
4 | }
--------------------------------------------------------------------------------
/extras/f_b.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/extras/f_b.jpg
--------------------------------------------------------------------------------
/macos/Flutter/Flutter-Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "ephemeral/Flutter-Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/assets/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/assets/icon.png
--------------------------------------------------------------------------------
/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/assets/logo.png
--------------------------------------------------------------------------------
/macos/Flutter/Flutter-Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "ephemeral/Flutter-Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/web/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/web/favicon.png
--------------------------------------------------------------------------------
/extras/bottom_bar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/extras/bottom_bar.png
--------------------------------------------------------------------------------
/web/icons/Icon-192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/web/icons/Icon-192.png
--------------------------------------------------------------------------------
/web/icons/Icon-512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/web/icons/Icon-512.png
--------------------------------------------------------------------------------
/extras/screenshot/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/extras/screenshot/1.png
--------------------------------------------------------------------------------
/extras/screenshot/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/extras/screenshot/2.png
--------------------------------------------------------------------------------
/extras/screenshot/3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/extras/screenshot/3.png
--------------------------------------------------------------------------------
/extras/screenshot/4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/extras/screenshot/4.png
--------------------------------------------------------------------------------
/extras/screenshot/5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/extras/screenshot/5.png
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1536M
2 | android.useAndroidX=true
3 | android.enableJetifier=true
4 |
--------------------------------------------------------------------------------
/macos/Runner/Configs/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "../../Flutter/Flutter-Debug.xcconfig"
2 | #include "Warnings.xcconfig"
3 |
--------------------------------------------------------------------------------
/web/icons/Icon-maskable-192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/web/icons/Icon-maskable-192.png
--------------------------------------------------------------------------------
/web/icons/Icon-maskable-512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/web/icons/Icon-maskable-512.png
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "cmake.configureOnOpen": false,
3 | "cmake.sourceDirectory": "${workspaceFolder}/linux"
4 | }
--------------------------------------------------------------------------------
/macos/Runner/Configs/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "../../Flutter/Flutter-Release.xcconfig"
2 | #include "Warnings.xcconfig"
3 |
--------------------------------------------------------------------------------
/macos/.gitignore:
--------------------------------------------------------------------------------
1 | # Flutter-related
2 | **/Flutter/ephemeral/
3 | **/Pods/
4 |
5 | # Xcode-related
6 | **/dgph
7 | **/xcuserdata/
8 |
--------------------------------------------------------------------------------
/android/app/src/main/ic_launcher-playstore.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/android/app/src/main/ic_launcher-playstore.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/ic_music.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/android/app/src/main/res/mipmap-hdpi/ic_music.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_music.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/android/app/src/main/res/mipmap-mdpi/ic_music.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_music.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/android/app/src/main/res/mipmap-xhdpi/ic_music.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_music.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/android/app/src/main/res/mipmap-xxhdpi/ic_music.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_music.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/android/app/src/main/res/mipmap-xxxhdpi/ic_music.png
--------------------------------------------------------------------------------
/server/requirements.txt:
--------------------------------------------------------------------------------
1 | blurhash==1.1.4
2 | blurhash_python==1.1.3
3 | meilisearch==0.22.1
4 | python-dotenv==0.21.0
5 | pytube==12.1.0
6 | requests==2.28.1
7 |
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/ic_launcher_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/android/app/src/main/res/mipmap-hdpi/ic_launcher_background.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_launcher_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/android/app/src/main/res/mipmap-mdpi/ic_launcher_background.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/android/app/src/main/res/mipmap-xhdpi/ic_launcher_background.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png
--------------------------------------------------------------------------------
/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png
--------------------------------------------------------------------------------
/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png
--------------------------------------------------------------------------------
/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png
--------------------------------------------------------------------------------
/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png
--------------------------------------------------------------------------------
/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_background.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
--------------------------------------------------------------------------------
/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsudip/sunday_suspense/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/custom.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Custom issue template
3 | about: Describe this issue template's purpose here.
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/linux/main.cc:
--------------------------------------------------------------------------------
1 | #include "my_application.h"
2 |
3 | int main(int argc, char** argv) {
4 | g_autoptr(MyApplication) app = my_application_new();
5 | return g_application_run(G_APPLICATION(app), argc, argv);
6 | }
7 |
--------------------------------------------------------------------------------
/android/app/src/main/kotlin/com/example/sunday_suspense/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.example.sunday_suspense
2 |
3 | import io.flutter.embedding.android.FlutterActivity
4 |
5 | class MainActivity: FlutterActivity() {
6 | }
7 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/macos/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/linux/flutter/generated_plugin_registrant.cc:
--------------------------------------------------------------------------------
1 | //
2 | // Generated file. Do not edit.
3 | //
4 |
5 | // clang-format off
6 |
7 | #include "generated_plugin_registrant.h"
8 |
9 |
10 | void fl_register_plugins(FlPluginRegistry* registry) {
11 | }
12 |
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | zipStoreBase=GRADLE_USER_HOME
4 | zipStorePath=wrapper/dists
5 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip
6 |
--------------------------------------------------------------------------------
/macos/Runner/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import Cocoa
2 | import FlutterMacOS
3 |
4 | @NSApplicationMain
5 | class AppDelegate: FlutterAppDelegate {
6 | override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
7 | return true
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/macos/Runner/Release.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.app-sandbox
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/firebase_app_id_file.json:
--------------------------------------------------------------------------------
1 | {
2 | "file_generated_by": "FlutterFire CLI",
3 | "purpose": "FirebaseAppID & ProjectID for this Firebase app in this directory",
4 | "GOOGLE_APP_ID": "1:50945720064:ios:f5424ba3bfce633aba3de5",
5 | "FIREBASE_PROJECT_ID": "sunday-suspense-14243",
6 | "GCM_SENDER_ID": "50945720064"
7 | }
--------------------------------------------------------------------------------
/macos/firebase_app_id_file.json:
--------------------------------------------------------------------------------
1 | {
2 | "file_generated_by": "FlutterFire CLI",
3 | "purpose": "FirebaseAppID & ProjectID for this Firebase app in this directory",
4 | "GOOGLE_APP_ID": "1:50945720064:ios:f5424ba3bfce633aba3de5",
5 | "FIREBASE_PROJECT_ID": "sunday-suspense-14243",
6 | "GCM_SENDER_ID": "50945720064"
7 | }
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/lib/screens/aboutpage.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/src/widgets/container.dart';
2 | import 'package:flutter/src/widgets/framework.dart';
3 |
4 | class AboutPageScreen extends StatelessWidget {
5 | const AboutPageScreen({super.key});
6 |
7 | @override
8 | Widget build(BuildContext context) {
9 | return Container();
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/lib/notifiers/play_button_notifier.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/foundation.dart';
2 |
3 | class PlayButtonNotifier extends ValueNotifier {
4 | PlayButtonNotifier() : super(_initialValue);
5 | static const _initialValue = ButtonState.paused;
6 | }
7 |
8 | enum ButtonState {
9 | paused,
10 | playing,
11 | loading,
12 | }
13 |
--------------------------------------------------------------------------------
/android/.gitignore:
--------------------------------------------------------------------------------
1 | gradle-wrapper.jar
2 | /.gradle
3 | /captures/
4 | /gradlew
5 | /gradlew.bat
6 | /local.properties
7 | GeneratedPluginRegistrant.java
8 |
9 | # Remember to never publicly share your keystore.
10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
11 | key.properties
12 | **/*.keystore
13 | **/*.jks
14 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md:
--------------------------------------------------------------------------------
1 | # Launch Screen Assets
2 |
3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory.
4 |
5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
--------------------------------------------------------------------------------
/linux/flutter/generated_plugin_registrant.h:
--------------------------------------------------------------------------------
1 | //
2 | // Generated file. Do not edit.
3 | //
4 |
5 | // clang-format off
6 |
7 | #ifndef GENERATED_PLUGIN_REGISTRANT_
8 | #define GENERATED_PLUGIN_REGISTRANT_
9 |
10 | #include
11 |
12 | // Registers Flutter plugins.
13 | void fl_register_plugins(FlPluginRegistry* registry);
14 |
15 | #endif // GENERATED_PLUGIN_REGISTRANT_
16 |
--------------------------------------------------------------------------------
/macos/Runner/DebugProfile.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.app-sandbox
6 |
7 | com.apple.security.cs.allow-jit
8 |
9 | com.apple.security.network.server
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import Flutter
3 |
4 | @UIApplicationMain
5 | @objc class AppDelegate: FlutterAppDelegate {
6 | override func application(
7 | _ application: UIApplication,
8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
9 | ) -> Bool {
10 | GeneratedPluginRegistrant.register(with: self)
11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/lib/utils.dart:
--------------------------------------------------------------------------------
1 | import 'package:date_time_format/date_time_format.dart';
2 |
3 | String calculateDuration(var length) {
4 | int hours = (length ~/ 3600);
5 | int minutes = (length ~/ 60) % 60;
6 | if (hours == 0) {
7 | return "$minutes mins";
8 | } else {
9 | return "$hours hrs $minutes mins";
10 | }
11 | }
12 |
13 | String showDate(String date) {
14 | DateTime dateTime = DateTime.parse(date);
15 | return DateTimeFormat.format(dateTime, format: 'jS M Y');
16 | }
17 |
--------------------------------------------------------------------------------
/linux/my_application.h:
--------------------------------------------------------------------------------
1 | #ifndef FLUTTER_MY_APPLICATION_H_
2 | #define FLUTTER_MY_APPLICATION_H_
3 |
4 | #include
5 |
6 | G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION,
7 | GtkApplication)
8 |
9 | /**
10 | * my_application_new:
11 | *
12 | * Creates a new Flutter-based application.
13 | *
14 | * Returns: a new #MyApplication.
15 | */
16 | MyApplication* my_application_new();
17 |
18 | #endif // FLUTTER_MY_APPLICATION_H_
19 |
--------------------------------------------------------------------------------
/macos/Runner/MainFlutterWindow.swift:
--------------------------------------------------------------------------------
1 | import Cocoa
2 | import FlutterMacOS
3 |
4 | class MainFlutterWindow: NSWindow {
5 | override func awakeFromNib() {
6 | let flutterViewController = FlutterViewController.init()
7 | let windowFrame = self.frame
8 | self.contentViewController = flutterViewController
9 | self.setFrame(windowFrame, display: true)
10 |
11 | RegisterGeneratedPlugins(registry: flutterViewController)
12 |
13 | super.awakeFromNib()
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/lib/notifiers/repeat_button_notifier.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/foundation.dart';
2 |
3 | class RepeatButtonNotifier extends ValueNotifier {
4 | RepeatButtonNotifier() : super(_initialValue);
5 | static const _initialValue = RepeatState.off;
6 |
7 | void nextState() {
8 | final next = (value.index + 1) % RepeatState.values.length;
9 | value = RepeatState.values[next];
10 | }
11 | }
12 |
13 | enum RepeatState {
14 | off,
15 | repeatSong,
16 | repeatPlaylist,
17 | }
18 |
--------------------------------------------------------------------------------
/android/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
3 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
4 | def properties = new Properties()
5 |
6 | assert localPropertiesFile.exists()
7 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
8 |
9 | def flutterSdkPath = properties.getProperty("flutter.sdk")
10 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
11 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
12 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-v21/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "LaunchImage.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "LaunchImage@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "LaunchImage@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/lib/notifiers/progress_notifier.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/foundation.dart';
2 |
3 | class ProgressNotifier extends ValueNotifier {
4 | ProgressNotifier() : super(_initialValue);
5 | static const _initialValue = ProgressBarState(
6 | current: Duration.zero,
7 | buffered: Duration.zero,
8 | total: Duration.zero,
9 | );
10 | }
11 |
12 | class ProgressBarState {
13 | const ProgressBarState({
14 | required this.current,
15 | required this.buffered,
16 | required this.total,
17 | });
18 | final Duration current;
19 | final Duration buffered;
20 | final Duration total;
21 | }
22 |
--------------------------------------------------------------------------------
/lib/services/service_locator.dart:
--------------------------------------------------------------------------------
1 | import 'package:audio_service/audio_service.dart';
2 | import 'package:flutter_dotenv/flutter_dotenv.dart';
3 | import 'package:meilisearch/meilisearch.dart';
4 |
5 | import '../page_manager.dart';
6 | import 'package:get_it/get_it.dart';
7 |
8 | GetIt getIt = GetIt.instance;
9 |
10 | Future setupServiceLocator() async {
11 | // page state
12 | getIt.registerSingleton(PageManager());
13 |
14 | // meilisearch
15 | getIt.registerSingleton(
16 | MeiliSearchClient('https://meilisearch-on-koyeb-imsudip.koyeb.app/', dotenv.env['MASTER_KEY']));
17 | }
18 |
--------------------------------------------------------------------------------
/macos/Runner/Configs/Warnings.xcconfig:
--------------------------------------------------------------------------------
1 | WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings
2 | GCC_WARN_UNDECLARED_SELECTOR = YES
3 | CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES
4 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE
5 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES
6 | CLANG_WARN_PRAGMA_PACK = YES
7 | CLANG_WARN_STRICT_PROTOTYPES = YES
8 | CLANG_WARN_COMMA = YES
9 | GCC_WARN_STRICT_SELECTOR_MATCH = YES
10 | CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES
11 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES
12 | GCC_WARN_SHADOW = YES
13 | CLANG_WARN_UNREACHABLE_CODE = YES
14 |
--------------------------------------------------------------------------------
/macos/Runner/Configs/AppInfo.xcconfig:
--------------------------------------------------------------------------------
1 | // Application-level settings for the Runner target.
2 | //
3 | // This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the
4 | // future. If not, the values below would default to using the project name when this becomes a
5 | // 'flutter create' template.
6 |
7 | // The application's name. By default this is also the title of the Flutter window.
8 | PRODUCT_NAME = sunday_suspense
9 |
10 | // The application's bundle identifier
11 | PRODUCT_BUNDLE_IDENTIFIER = com.example.sundaySuspense
12 |
13 | // The copyright displayed in application information
14 | PRODUCT_COPYRIGHT = Copyright © 2022 com.example. All rights reserved.
15 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/ios/.gitignore:
--------------------------------------------------------------------------------
1 | **/dgph
2 | *.mode1v3
3 | *.mode2v3
4 | *.moved-aside
5 | *.pbxuser
6 | *.perspectivev3
7 | **/*sync/
8 | .sconsign.dblite
9 | .tags*
10 | **/.vagrant/
11 | **/DerivedData/
12 | Icon?
13 | **/Pods/
14 | **/.symlinks/
15 | profile
16 | xcuserdata
17 | **/.generated/
18 | Flutter/App.framework
19 | Flutter/Flutter.framework
20 | Flutter/Flutter.podspec
21 | Flutter/Generated.xcconfig
22 | Flutter/ephemeral/
23 | Flutter/app.flx
24 | Flutter/app.zip
25 | Flutter/flutter_assets/
26 | Flutter/flutter_export_environment.sh
27 | ServiceDefinitions.json
28 | Runner/GeneratedPluginRegistrant.*
29 |
30 | # Exceptions to above rules.
31 | !default.mode1v3
32 | !default.mode2v3
33 | !default.pbxuser
34 | !default.perspectivev3
35 |
--------------------------------------------------------------------------------
/lib/generated_plugin_registrant.dart:
--------------------------------------------------------------------------------
1 | //
2 | // Generated file. Do not edit.
3 | //
4 |
5 | // ignore_for_file: directives_ordering
6 | // ignore_for_file: lines_longer_than_80_chars
7 | // ignore_for_file: depend_on_referenced_packages
8 |
9 | import 'package:audio_service_web/audio_service_web.dart';
10 | import 'package:audio_session/audio_session_web.dart';
11 | import 'package:just_audio_web/just_audio_web.dart';
12 |
13 | import 'package:flutter_web_plugins/flutter_web_plugins.dart';
14 |
15 | // ignore: public_member_api_docs
16 | void registerPlugins(Registrar registrar) {
17 | AudioServiceWeb.registerWith(registrar);
18 | AudioSessionWeb.registerWith(registrar);
19 | JustAudioPlugin.registerWith(registrar);
20 | registrar.registerMessageHandler();
21 | }
22 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | ext.kotlin_version = '1.6.10'
3 | repositories {
4 | google()
5 | mavenCentral()
6 | }
7 |
8 | dependencies {
9 | classpath 'com.android.tools.build:gradle:7.1.2'
10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
11 | classpath 'com.google.gms:google-services:4.3.13'
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | google()
18 | mavenCentral()
19 | }
20 | }
21 |
22 | rootProject.buildDir = '../build'
23 | subprojects {
24 | project.buildDir = "${rootProject.buildDir}/${project.name}"
25 | }
26 | subprojects {
27 | project.evaluationDependsOn(':app')
28 | }
29 |
30 | task clean(type: Delete) {
31 | delete rootProject.buildDir
32 | }
33 |
--------------------------------------------------------------------------------
/.github/workflows/issuenotifier.yml:
--------------------------------------------------------------------------------
1 | name: Issue Notifier
2 | on:
3 | issues:
4 | types:
5 | - reopened
6 | - opened
7 |
8 | jobs:
9 | notify:
10 | runs-on: ubuntu-latest
11 | permissions:
12 | issues: read
13 |
14 | steps:
15 | - name: Commit on Telegram
16 | uses: appleboy/telegram-action@master
17 | with:
18 | to: ${{ secrets.TELEGRAM_TO }}
19 | token: ${{ secrets.TELEGRAM_TOKEN }}
20 | format: markdown
21 | disable_web_page_preview: true
22 | message: |
23 | New Issue ([#${{ github.event.issue.number }}](${{ github.event.issue.html_url }})) opened by [#${{ github.event.issue.user.login }}](${{ github.event.issue.user.html_url }}).
24 | Issue: ${{ github.event.issue.title }}
25 |
26 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
4 | patreon: # Replace with a single Patreon username
5 | open_collective: # Replace with a single Open Collective username
6 | ko_fi: # Replace with a single Ko-fi username
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: # Replace with a single IssueHunt username
11 | otechie: # Replace with a single Otechie username
12 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
13 | custom: ["https://www.buymeacoffee.com/imsudip"]
14 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | // Use IntelliSense to learn about possible attributes.
3 | // Hover to view descriptions of existing attributes.
4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5 | "version": "0.2.0",
6 | "configurations": [
7 | {
8 | "name": "sunday_suspense",
9 | "request": "launch",
10 | "type": "dart"
11 | },
12 | {
13 | "name": "sunday_suspense (profile mode)",
14 | "request": "launch",
15 | "type": "dart",
16 | "flutterMode": "profile"
17 | },
18 | {
19 | "name": "sunday_suspense (release mode)",
20 | "request": "launch",
21 | "type": "dart",
22 | "flutterMode": "release"
23 | }
24 | ]
25 | }
--------------------------------------------------------------------------------
/linux/flutter/generated_plugins.cmake:
--------------------------------------------------------------------------------
1 | #
2 | # Generated file, do not edit.
3 | #
4 |
5 | list(APPEND FLUTTER_PLUGIN_LIST
6 | )
7 |
8 | list(APPEND FLUTTER_FFI_PLUGIN_LIST
9 | )
10 |
11 | set(PLUGIN_BUNDLED_LIBRARIES)
12 |
13 | foreach(plugin ${FLUTTER_PLUGIN_LIST})
14 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin})
15 | target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
16 | list(APPEND PLUGIN_BUNDLED_LIBRARIES $)
17 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
18 | endforeach(plugin)
19 |
20 | foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
21 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin})
22 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
23 | endforeach(ffi_plugin)
24 |
--------------------------------------------------------------------------------
/server/backup.py:
--------------------------------------------------------------------------------
1 | import os
2 | from dotenv import load_dotenv
3 | import json
4 | import meilisearch
5 |
6 |
7 | load_dotenv()
8 | meiliClient = meilisearch.Client(
9 | "https://meilisearch-on-koyeb-imsudip.koyeb.app/", os.getenv('MASTER_KEY'))
10 | try:
11 | index = meiliClient.index('sunday')
12 | # get all documents and save to json file
13 | all_docs = index.get_documents({'limit': 100000})
14 | d = all_docs.results
15 | d2 = []
16 | for item in d:
17 | d2.append(item.__dict__['_Document__doc'])
18 | if len(d2) > 0:
19 | with open('sunday.json', 'w', encoding='utf-8') as f:
20 | json.dump(d2, f, ensure_ascii=False, indent=4)
21 |
22 | print("total docs count: "+str(len(d2)))
23 |
24 | # catch exception
25 | except Exception as e:
26 | print(e)
27 | print("error")
28 | finally:
29 | print("done")
30 |
--------------------------------------------------------------------------------
/ios/Flutter/AppFrameworkInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | App
9 | CFBundleIdentifier
10 | io.flutter.flutter.app
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | App
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1.0
23 | MinimumOSVersion
24 | 11.0
25 |
26 |
27 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .buildlog/
9 | .history
10 | .svn/
11 | migrate_working_dir/
12 |
13 | # IntelliJ related
14 | *.iml
15 | *.ipr
16 | *.iws
17 | .idea/
18 |
19 | # The .vscode folder contains launch configuration and tasks you configure in
20 | # VS Code which you may wish to be included in version control, so this line
21 | # is commented out by default.
22 | #.vscode/
23 |
24 | # Flutter/Dart/Pub related
25 | **/doc/api/
26 | **/ios/Flutter/.last_build_id
27 | .dart_tool/
28 | .flutter-plugins
29 | .flutter-plugins-dependencies
30 | .packages
31 | .pub-cache/
32 | .pub/
33 | /build/
34 |
35 | # Symbolication related
36 | app.*.symbols
37 |
38 | # Obfuscation related
39 | app.*.map.json
40 |
41 | # Android Studio will place build artifacts here
42 | /android/app/debug
43 | /android/app/profile
44 | /android/app/release
45 |
46 | *.env
47 |
48 | .fvm/flutter_sdk
49 | node_modules
50 |
--------------------------------------------------------------------------------
/server/checkup_db.py:
--------------------------------------------------------------------------------
1 | import os
2 | from dotenv import load_dotenv
3 | import build_new_item
4 | import requests
5 | import json
6 | import meilisearch
7 |
8 |
9 | load_dotenv()
10 | meiliClient = meilisearch.Client(
11 | "https://meilisearch-on-koyeb-imsudip.koyeb.app/", os.getenv('MASTER_KEY'))
12 | # firebase_key = os.getenv('FIREBASE_KEY')
13 |
14 |
15 | # fetch newest item from meilisearch
16 |
17 | def get_newest_items():
18 | index = meiliClient.index('sunday')
19 | # get the newest item
20 | all_docs = index.search(" ", {'limit': 5, 'sort': ['timestamp:desc']})
21 | d = all_docs['hits']
22 | # print(d)
23 | for item in d:
24 | if (item['length'] == 0):
25 | print('Updating item...')
26 | print(item['title'])
27 | new_item = build_new_item.getVideoDataFromLink(item['url'])
28 | index.update_documents([new_item])
29 | print('Item updated!')
30 |
31 |
32 | get_newest_items()
33 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Desktop (please complete the following information):**
27 | - OS: [e.g. iOS]
28 | - Browser [e.g. chrome, safari]
29 | - Version [e.g. 22]
30 |
31 | **Smartphone (please complete the following information):**
32 | - Device: [e.g. iPhone6]
33 | - OS: [e.g. iOS8.1]
34 | - Browser [e.g. stock browser, safari]
35 | - Version [e.g. 22]
36 |
37 | **Additional context**
38 | Add any other context about the problem here.
39 |
--------------------------------------------------------------------------------
/.github/workflows/update_db.yml:
--------------------------------------------------------------------------------
1 | name: update_db
2 |
3 | on:
4 | schedule:
5 | - cron: "0 */4 * * 0" # every 4 hours on Sunday
6 | workflow_dispatch:
7 |
8 | jobs:
9 | build:
10 | runs-on: ubuntu-latest
11 | steps:
12 | - uses: actions/checkout@v3
13 | with:
14 | token: ${{ secrets.PAT }}
15 | - name: checkout repo content
16 | uses: actions/checkout@v2 # checkout the repository content to github runner
17 |
18 | - name: setup python
19 | uses: actions/setup-python@v4
20 | with:
21 | python-version: "3.9" # install the python version needed
22 |
23 | - name: install python packages
24 | run: |
25 | cd ./server
26 | python -m pip install --upgrade pip
27 | pip install -r requirements.txt
28 |
29 | - name: execute py script # run main.py
30 | env:
31 | MASTER_KEY: ${{ secrets.MASTER_KEY }}
32 | FIREBASE_KEY: ${{ secrets.FIREBASE_KEY }}
33 | run: |
34 | cd ./server
35 | python main.py
36 |
--------------------------------------------------------------------------------
/web/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sunday_suspense",
3 | "short_name": "sunday_suspense",
4 | "start_url": ".",
5 | "display": "standalone",
6 | "background_color": "#0175C2",
7 | "theme_color": "#0175C2",
8 | "description": "A new Flutter project.",
9 | "orientation": "portrait-primary",
10 | "prefer_related_applications": false,
11 | "icons": [
12 | {
13 | "src": "icons/Icon-192.png",
14 | "sizes": "192x192",
15 | "type": "image/png"
16 | },
17 | {
18 | "src": "icons/Icon-512.png",
19 | "sizes": "512x512",
20 | "type": "image/png"
21 | },
22 | {
23 | "src": "icons/Icon-maskable-192.png",
24 | "sizes": "192x192",
25 | "type": "image/png",
26 | "purpose": "maskable"
27 | },
28 | {
29 | "src": "icons/Icon-maskable-512.png",
30 | "sizes": "512x512",
31 | "type": "image/png",
32 | "purpose": "maskable"
33 | }
34 | ]
35 | }
36 |
--------------------------------------------------------------------------------
/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/android/app/src/main/res/values-night/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/test/widget_test.dart:
--------------------------------------------------------------------------------
1 | // This is a basic Flutter widget test.
2 | //
3 | // To perform an interaction with a widget in your test, use the WidgetTester
4 | // utility in the flutter_test package. For example, you can send tap and scroll
5 | // gestures. You can also use WidgetTester to find child widgets in the widget
6 | // tree, read text, and verify that the values of widget properties are correct.
7 |
8 | import 'package:flutter/material.dart';
9 | import 'package:flutter_test/flutter_test.dart';
10 |
11 | import 'package:sunday_suspense/main.dart';
12 |
13 | void main() {
14 | testWidgets('Counter increments smoke test', (WidgetTester tester) async {
15 | // Build our app and trigger a frame.
16 | await tester.pumpWidget(MyApp());
17 |
18 | // Verify that our counter starts at 0.
19 | expect(find.text('0'), findsOneWidget);
20 | expect(find.text('1'), findsNothing);
21 |
22 | // Tap the '+' icon and trigger a frame.
23 | await tester.tap(find.byIcon(Icons.add));
24 | await tester.pump();
25 |
26 | // Verify that our counter has incremented.
27 | expect(find.text('0'), findsNothing);
28 | expect(find.text('1'), findsOneWidget);
29 | });
30 | }
31 |
--------------------------------------------------------------------------------
/macos/Runner/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIconFile
10 |
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | $(FLUTTER_BUILD_NAME)
21 | CFBundleVersion
22 | $(FLUTTER_BUILD_NUMBER)
23 | LSMinimumSystemVersion
24 | $(MACOSX_DEPLOYMENT_TARGET)
25 | NSHumanReadableCopyright
26 | $(PRODUCT_COPYRIGHT)
27 | NSMainNibFile
28 | MainMenu
29 | NSPrincipalClass
30 | NSApplication
31 |
32 |
33 |
--------------------------------------------------------------------------------
/server/checkplaylist.py:
--------------------------------------------------------------------------------
1 | import requests
2 |
3 | adventure_id = 'PLq71IJk8mCV4bl9PzA1RJ6ipr0TBw-7VK'
4 | crime_id = 'PLq71IJk8mCV4YmG5ULzAq2QCZqdDRWLhO'
5 | horror_id = 'PLq71IJk8mCV4vFBqzx4JmLpWFtvpl93Sv'
6 | thriller_id = 'PLq71IJk8mCV7tZ7b3BLx5lZitMvlGL-9p'
7 |
8 |
9 | def get_rss_feed(playlist_id):
10 | url = 'https://api.rss2json.com/v1/api.json?rss_url=https://www.youtube.com/feeds/videos.xml?playlist_id=' + playlist_id
11 | response = requests.get(url)
12 | data = response.json()
13 | video_ids = []
14 | for item in data['items']:
15 | video_ids.append(item['link'].split('=')[1])
16 | return video_ids
17 |
18 |
19 | def check_playlist_inclusion(video_id):
20 | adventure_ids = get_rss_feed(adventure_id)
21 | crime_ids = get_rss_feed(crime_id)
22 | horror_ids = get_rss_feed(horror_id)
23 | thriller_ids = get_rss_feed(thriller_id)
24 |
25 | tags = []
26 | if video_id in adventure_ids:
27 | tags.append('adventure')
28 | if video_id in crime_ids:
29 | tags.append('crime')
30 | if video_id in horror_ids:
31 | tags.append('horror')
32 | if video_id in thriller_ids:
33 | tags.append('thriller')
34 | return tags
35 |
--------------------------------------------------------------------------------
/ios/Runner/GoogleService-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CLIENT_ID
6 | 50945720064-1a40ats3fthtkvi1p6in3ih89aj5dnkj.apps.googleusercontent.com
7 | REVERSED_CLIENT_ID
8 | com.googleusercontent.apps.50945720064-1a40ats3fthtkvi1p6in3ih89aj5dnkj
9 | API_KEY
10 | AIzaSyBGsEz7Ab__YfMU_ejLtsSww7JP4nI8Qig
11 | GCM_SENDER_ID
12 | 50945720064
13 | PLIST_VERSION
14 | 1
15 | BUNDLE_ID
16 | com.example.sundaySuspense
17 | PROJECT_ID
18 | sunday-suspense-14243
19 | STORAGE_BUCKET
20 | sunday-suspense-14243.appspot.com
21 | IS_ADS_ENABLED
22 |
23 | IS_ANALYTICS_ENABLED
24 |
25 | IS_APPINVITE_ENABLED
26 |
27 | IS_GCM_ENABLED
28 |
29 | IS_SIGNIN_ENABLED
30 |
31 | GOOGLE_APP_ID
32 | 1:50945720064:ios:f5424ba3bfce633aba3de5
33 |
34 |
--------------------------------------------------------------------------------
/macos/Runner/GoogleService-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CLIENT_ID
6 | 50945720064-1a40ats3fthtkvi1p6in3ih89aj5dnkj.apps.googleusercontent.com
7 | REVERSED_CLIENT_ID
8 | com.googleusercontent.apps.50945720064-1a40ats3fthtkvi1p6in3ih89aj5dnkj
9 | API_KEY
10 | AIzaSyBGsEz7Ab__YfMU_ejLtsSww7JP4nI8Qig
11 | GCM_SENDER_ID
12 | 50945720064
13 | PLIST_VERSION
14 | 1
15 | BUNDLE_ID
16 | com.example.sundaySuspense
17 | PROJECT_ID
18 | sunday-suspense-14243
19 | STORAGE_BUCKET
20 | sunday-suspense-14243.appspot.com
21 | IS_ADS_ENABLED
22 |
23 | IS_ANALYTICS_ENABLED
24 |
25 | IS_APPINVITE_ENABLED
26 |
27 | IS_GCM_ENABLED
28 |
29 | IS_SIGNIN_ENABLED
30 |
31 | GOOGLE_APP_ID
32 | 1:50945720064:ios:f5424ba3bfce633aba3de5
33 |
34 |
--------------------------------------------------------------------------------
/lib/widgets/searchbar.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/cupertino.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:iconsax/iconsax.dart';
4 | import '../ui/app_colors.dart';
5 | import '../ui/text_styles.dart';
6 |
7 | class SearchBar extends StatelessWidget {
8 | const SearchBar({super.key});
9 |
10 | @override
11 | Widget build(BuildContext context) {
12 | return Container(
13 | height: 54,
14 | width: MediaQuery.of(context).size.width,
15 | margin: const EdgeInsets.symmetric(horizontal: 20, vertical: 4),
16 | child: CupertinoTextField(
17 | placeholder: 'Search',
18 | readOnly: true,
19 | style: AppTextStyle.bodytext1,
20 | placeholderStyle: AppTextStyle.bodytext1.copyWith(color: AppColors.textSecondaryColor),
21 | padding: const EdgeInsets.symmetric(horizontal: 20),
22 | prefix: const Padding(
23 | padding: EdgeInsets.only(left: 20),
24 | child: Icon(
25 | Iconsax.search_normal_1,
26 | color: AppColors.textSecondaryColor,
27 | ),
28 | ),
29 | decoration: BoxDecoration(
30 | color: Colors.white.withOpacity(0.1),
31 | borderRadius: BorderRadius.circular(16),
32 | ),
33 | ),
34 | );
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/macos/Flutter/GeneratedPluginRegistrant.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Generated file. Do not edit.
3 | //
4 |
5 | import FlutterMacOS
6 | import Foundation
7 |
8 | import audio_service
9 | import audio_session
10 | import cloud_firestore
11 | import firebase_core
12 | import firebase_messaging
13 | import flutter_local_notifications
14 | import just_audio
15 | import package_info_plus_macos
16 | import path_provider_macos
17 | import sqflite
18 |
19 | func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
20 | AudioServicePlugin.register(with: registry.registrar(forPlugin: "AudioServicePlugin"))
21 | AudioSessionPlugin.register(with: registry.registrar(forPlugin: "AudioSessionPlugin"))
22 | FLTFirebaseFirestorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseFirestorePlugin"))
23 | FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin"))
24 | FLTFirebaseMessagingPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseMessagingPlugin"))
25 | FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin"))
26 | JustAudioPlugin.register(with: registry.registrar(forPlugin: "JustAudioPlugin"))
27 | FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin"))
28 | PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
29 | SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
30 | }
31 |
--------------------------------------------------------------------------------
/android/app/google-services.json:
--------------------------------------------------------------------------------
1 | {
2 | "project_info": {
3 | "project_number": "50945720064",
4 | "project_id": "sunday-suspense-14243",
5 | "storage_bucket": "sunday-suspense-14243.appspot.com"
6 | },
7 | "client": [
8 | {
9 | "client_info": {
10 | "mobilesdk_app_id": "1:50945720064:android:ca46877ec54f647cba3de5",
11 | "android_client_info": {
12 | "package_name": "com.example.sunday_suspense"
13 | }
14 | },
15 | "oauth_client": [
16 | {
17 | "client_id": "50945720064-69rfml9vv77g3ou0414gf048uugl4i9j.apps.googleusercontent.com",
18 | "client_type": 3
19 | }
20 | ],
21 | "api_key": [
22 | {
23 | "current_key": "AIzaSyAnCIzi6qKv1LJKmKhqR1GLu6fVqYsvVwg"
24 | }
25 | ],
26 | "services": {
27 | "appinvite_service": {
28 | "other_platform_oauth_client": [
29 | {
30 | "client_id": "50945720064-69rfml9vv77g3ou0414gf048uugl4i9j.apps.googleusercontent.com",
31 | "client_type": 3
32 | },
33 | {
34 | "client_id": "50945720064-1a40ats3fthtkvi1p6in3ih89aj5dnkj.apps.googleusercontent.com",
35 | "client_type": 2,
36 | "ios_info": {
37 | "bundle_id": "com.example.sundaySuspense"
38 | }
39 | }
40 | ]
41 | }
42 | }
43 | }
44 | ],
45 | "configuration_version": "1"
46 | }
--------------------------------------------------------------------------------
/lib/ui/app_colors.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class AppColors {
4 | static const Color primaryColor = Color(0xFF9a0e13);
5 | static const Color accentColor = Color(0xFF282828);
6 | static const Color backgroundColor = Color(0xFF111111);
7 | static const Color textPrimaryColor = Color(0xFFffffff);
8 | static const Color textSecondaryColor = Color(0xFF6A6969);
9 | static const Color primaryWhiteColor = Color(0xFFFFFFFF);
10 | static const Color errorColor = Color.fromARGB(255, 255, 150, 150);
11 |
12 | static MaterialColor createMaterialColor(Color color) {
13 | List strengths = [.05];
14 | final swatch = {};
15 | final int r = color.red, g = color.green, b = color.blue;
16 |
17 | for (int i = 1; i < 10; i++) {
18 | strengths.add(0.1 * i);
19 | }
20 | for (var strength in strengths) {
21 | final double ds = 0.5 - strength;
22 | swatch[(strength * 1000).round()] = Color.fromRGBO(
23 | r + ((ds < 0 ? r : (255 - r)) * ds).round(),
24 | g + ((ds < 0 ? g : (255 - g)) * ds).round(),
25 | b + ((ds < 0 ? b : (255 - b)) * ds).round(),
26 | 1,
27 | );
28 | }
29 | return MaterialColor(color.value, swatch);
30 | }
31 |
32 | static ColorScheme lightScheme = const ColorScheme.light(
33 | primary: primaryColor,
34 | secondary: accentColor,
35 | );
36 |
37 | static ColorScheme darkScheme = const ColorScheme.dark(
38 | primary: primaryColor,
39 | secondary: accentColor,
40 | );
41 | }
42 |
--------------------------------------------------------------------------------
/lib/main.dart:
--------------------------------------------------------------------------------
1 | // import 'package:firebase_core/firebase_core.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:flutter_dotenv/flutter_dotenv.dart';
4 | import 'package:get/get_navigation/src/root/get_material_app.dart';
5 | import 'package:get_storage/get_storage.dart';
6 | import 'package:sunday_suspense/services/notification_service.dart';
7 | import 'screens/root.dart';
8 | import 'ui/my_theme.dart';
9 | import 'page_manager.dart';
10 | import 'services/service_locator.dart';
11 |
12 | void main() async {
13 | await GetStorage.init("prefs");
14 | await GetStorage.init('HistoryBox');
15 | await dotenv.load(fileName: ".env");
16 | await setupServiceLocator();
17 | runApp(const MyApp());
18 | await fcmFunctions.initApp();
19 | await fcmFunctions.iosWebPermission();
20 | fcmFunctions.foreGroundMessageListener();
21 | await fcmFunctions.subscripeToTopics("news");
22 | }
23 |
24 | class MyApp extends StatefulWidget {
25 | const MyApp({super.key});
26 |
27 | @override
28 | State createState() => _MyAppState();
29 | }
30 |
31 | class _MyAppState extends State {
32 | @override
33 | void initState() {
34 | super.initState();
35 | getIt().init();
36 | }
37 |
38 | @override
39 | void dispose() {
40 | getIt().dispose();
41 | super.dispose();
42 | }
43 |
44 | @override
45 | Widget build(BuildContext context) {
46 | return GetMaterialApp(
47 | theme: MyTheme.darkTheme,
48 | home: const RootWidget(),
49 | );
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: sunday_suspense
2 | description: A new Flutter project.
3 | publish_to: "none" # Remove this line if you wish to publish to pub.dev
4 |
5 | version: 1.0.5+6
6 |
7 | environment:
8 | sdk: ">=2.18.1 <3.0.0"
9 |
10 | dependencies:
11 | animated_icon_button: ^1.0.2
12 | audio_video_progress_bar: ^0.10.0
13 | cached_network_image: ^3.2.2
14 | cloud_firestore: ^3.4.7
15 | cupertino_icons: ^1.0.2
16 | date_time_format: ^2.0.1
17 | debounce_throttle: ^2.0.0
18 | dot_navigation_bar: ^1.0.1+4
19 | eva_icons_flutter: ^3.1.0
20 | firebase_core: ^1.22.0
21 | firebase_messaging: ^11.4.2
22 | flutter:
23 | sdk: flutter
24 | flutter_bounceable: ^1.0.3
25 | flutter_dotenv: ^5.0.2
26 | flutter_local_notifications: any
27 | get: ^4.6.5
28 | get_it: ^7.2.0
29 | get_storage: ^2.0.3
30 | google_fonts: ^3.0.1
31 | iconsax: ^0.0.8
32 | just_audio: ^0.9.28
33 | just_audio_background: ^0.0.1-beta.7
34 | loadmore: ^2.0.1
35 | lottie: ^1.4.3
36 | meilisearch: ^0.6.0
37 | octo_image: ^1.0.2
38 | package_info_plus: ^1.4.3+1
39 | solid_bottom_sheet: ^0.1.10
40 | youtube_explode_dart: ^1.12.2
41 |
42 | dev_dependencies:
43 | flutter_lints: ^2.0.0
44 | flutter_test:
45 | sdk: flutter
46 | icons_launcher: ^2.0.5
47 |
48 | icons_launcher:
49 | image_path: "assets/icon.png"
50 | platforms:
51 | android:
52 | enable: true
53 | ios:
54 | enable: true
55 |
56 | flutter:
57 | uses-material-design: true
58 | assets:
59 | - assets/
60 | - assets/lottie/
61 | - .env
62 |
--------------------------------------------------------------------------------
/.github/workflows/prchecker.yml:
--------------------------------------------------------------------------------
1 | name: PR Check
2 |
3 | on:
4 | pull_request:
5 | branches:
6 | - master
7 |
8 | jobs:
9 | build:
10 | runs-on: ubuntu-latest
11 |
12 | steps:
13 | - uses: actions/checkout@v1
14 |
15 | # Setup Java environment in order to build the Android app.
16 | - uses: actions/setup-java@v1
17 | with:
18 | java-version: "12.x"
19 |
20 | # Gradle cache for faster builds
21 | - uses: actions/cache@v2
22 | with:
23 | path: |
24 | ~/.gradle/caches
25 | ~/.gradle/wrapper
26 | key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }}
27 | restore-keys: |
28 | ${{ runner.os }}-gradle-
29 | # Setup the flutter environment.
30 | - uses: subosito/flutter-action@v1
31 | with:
32 | channel: "stable"
33 |
34 | # Get flutter dependencies.
35 | - run: flutter pub get
36 |
37 | # Check for any formatting issues in the code.
38 | - run: flutter format --set-exit-if-changed .
39 |
40 | # Statically analyze the Dart code for any errors.
41 | - run: flutter analyze .
42 |
43 | # Run widget tests for our flutter project.
44 | # - run: flutter test
45 |
46 | # Build apk.
47 | - run: flutter build apk --release
48 |
49 | # Upload generated apk to the artifacts.
50 | - uses: actions/upload-artifact@v1
51 | with:
52 | name: app-release.apk
53 | path: build/app/outputs/apk/release/app-release.apk
54 |
--------------------------------------------------------------------------------
/analysis_options.yaml:
--------------------------------------------------------------------------------
1 | # This file configures the analyzer, which statically analyzes Dart code to
2 | # check for errors, warnings, and lints.
3 | #
4 | # The issues identified by the analyzer are surfaced in the UI of Dart-enabled
5 | # IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
6 | # invoked from the command line by running `flutter analyze`.
7 |
8 | # The following line activates a set of recommended lints for Flutter apps,
9 | # packages, and plugins designed to encourage good coding practices.
10 | include: package:flutter_lints/flutter.yaml
11 |
12 | linter:
13 | # The lint rules applied to this project can be customized in the
14 | # section below to disable rules from the `package:flutter_lints/flutter.yaml`
15 | # included above or to enable additional rules. A list of all available lints
16 | # and their documentation is published at
17 | # https://dart-lang.github.io/linter/lints/index.html.
18 | #
19 | # Instead of disabling a lint rule for the entire project in the
20 | # section below, it can also be suppressed for a single line of code
21 | # or a specific dart file by using the `// ignore: name_of_lint` and
22 | # `// ignore_for_file: name_of_lint` syntax on the line or in the file
23 | # producing the lint.
24 | rules:
25 | # avoid_print: false # Uncomment to disable the `avoid_print` rule
26 | # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
27 |
28 | # Additional information about this file can be found at
29 | # https://dart.dev/guides/language/analysis-options
30 |
--------------------------------------------------------------------------------
/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "16x16",
5 | "idiom" : "mac",
6 | "filename" : "app_icon_16.png",
7 | "scale" : "1x"
8 | },
9 | {
10 | "size" : "16x16",
11 | "idiom" : "mac",
12 | "filename" : "app_icon_32.png",
13 | "scale" : "2x"
14 | },
15 | {
16 | "size" : "32x32",
17 | "idiom" : "mac",
18 | "filename" : "app_icon_32.png",
19 | "scale" : "1x"
20 | },
21 | {
22 | "size" : "32x32",
23 | "idiom" : "mac",
24 | "filename" : "app_icon_64.png",
25 | "scale" : "2x"
26 | },
27 | {
28 | "size" : "128x128",
29 | "idiom" : "mac",
30 | "filename" : "app_icon_128.png",
31 | "scale" : "1x"
32 | },
33 | {
34 | "size" : "128x128",
35 | "idiom" : "mac",
36 | "filename" : "app_icon_256.png",
37 | "scale" : "2x"
38 | },
39 | {
40 | "size" : "256x256",
41 | "idiom" : "mac",
42 | "filename" : "app_icon_256.png",
43 | "scale" : "1x"
44 | },
45 | {
46 | "size" : "256x256",
47 | "idiom" : "mac",
48 | "filename" : "app_icon_512.png",
49 | "scale" : "2x"
50 | },
51 | {
52 | "size" : "512x512",
53 | "idiom" : "mac",
54 | "filename" : "app_icon_512.png",
55 | "scale" : "1x"
56 | },
57 | {
58 | "size" : "512x512",
59 | "idiom" : "mac",
60 | "filename" : "app_icon_1024.png",
61 | "scale" : "2x"
62 | }
63 | ],
64 | "info" : {
65 | "version" : 1,
66 | "author" : "xcode"
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/ios/Runner/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/.metadata:
--------------------------------------------------------------------------------
1 | # This file tracks properties of this Flutter project.
2 | # Used by Flutter tool to assess capabilities and perform upgrades etc.
3 | #
4 | # This file should be version controlled.
5 |
6 | version:
7 | revision: e3c29ec00c9c825c891d75054c63fcc46454dca1
8 | channel: stable
9 |
10 | project_type: app
11 |
12 | # Tracks metadata for the flutter migrate command
13 | migration:
14 | platforms:
15 | - platform: root
16 | create_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1
17 | base_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1
18 | - platform: android
19 | create_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1
20 | base_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1
21 | - platform: ios
22 | create_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1
23 | base_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1
24 | - platform: linux
25 | create_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1
26 | base_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1
27 | - platform: macos
28 | create_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1
29 | base_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1
30 | - platform: web
31 | create_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1
32 | base_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1
33 | - platform: windows
34 | create_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1
35 | base_revision: e3c29ec00c9c825c891d75054c63fcc46454dca1
36 |
37 | # User provided section
38 |
39 | # List of Local paths (relative to this file) that should be
40 | # ignored by the migrate tool.
41 | #
42 | # Files that are not part of the templates will be ignored by default.
43 | unmanaged_files:
44 | - 'lib/main.dart'
45 | - 'ios/Runner.xcodeproj/project.pbxproj'
46 |
--------------------------------------------------------------------------------
/ios/Runner/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleDisplayName
8 | Sunday Suspense
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | sunday_suspense
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | $(FLUTTER_BUILD_NAME)
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | $(FLUTTER_BUILD_NUMBER)
25 | LSRequiresIPhoneOS
26 |
27 | UILaunchStoryboardName
28 | LaunchScreen
29 | UIMainStoryboardFile
30 | Main
31 | UISupportedInterfaceOrientations
32 |
33 | UIInterfaceOrientationPortrait
34 | UIInterfaceOrientationLandscapeLeft
35 | UIInterfaceOrientationLandscapeRight
36 |
37 | UISupportedInterfaceOrientations~ipad
38 |
39 | UIInterfaceOrientationPortrait
40 | UIInterfaceOrientationPortraitUpsideDown
41 | UIInterfaceOrientationLandscapeLeft
42 | UIInterfaceOrientationLandscapeRight
43 |
44 | UIViewControllerBasedStatusBarAppearance
45 |
46 | CADisableMinimumFrameDurationOnPhone
47 |
48 | UIApplicationSupportsIndirectInputEvents
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/web/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 | sunday_suspense
33 |
34 |
35 |
39 |
40 |
41 |
42 |
43 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/lib/ui/text_styles.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:google_fonts/google_fonts.dart';
3 |
4 | import 'app_colors.dart';
5 |
6 | class AppTextStyle {
7 | static String? get fontFamily => GoogleFonts.poppins().fontFamily;
8 | //static String? get fontFamily => GoogleFonts.yanoneKaffeesatz().fontFamily;
9 |
10 | // Google font
11 | static TextStyle get defaultFontStyle => GoogleFonts.poppins();
12 |
13 | // if we need to change a style
14 |
15 | // Headline 1
16 | static TextStyle get headline1 => GoogleFonts.poppins(
17 | fontSize: 28.0,
18 | fontWeight: FontWeight.w700,
19 | color: AppColors.primaryColor,
20 | );
21 | // Headline 2
22 | static TextStyle get headline2 => GoogleFonts.poppins(
23 | fontSize: 22.0,
24 | fontWeight: FontWeight.w600,
25 | );
26 | // Headline 3
27 | static TextStyle get headline3 => GoogleFonts.poppins(
28 | fontSize: 18.0,
29 | fontWeight: FontWeight.w600,
30 | );
31 | static TextStyle get subHeading => GoogleFonts.poppins(fontSize: 16, fontWeight: FontWeight.w600, height: 1.3);
32 | // Bodytext 1
33 | static TextStyle get bodytext1 => GoogleFonts.poppins(
34 | fontSize: 16.0,
35 | color: Colors.white,
36 | );
37 | // Bodytext 2
38 | static TextStyle get bodytext2 => GoogleFonts.poppins(
39 | fontSize: 14.0,
40 | color: Colors.white60,
41 | );
42 | // Caption
43 | static TextStyle get caption =>
44 | GoogleFonts.poppins(fontSize: 12.0, fontWeight: FontWeight.w400, color: AppColors.textSecondaryColor);
45 | static TextStyle get regular16 => GoogleFonts.poppins(
46 | fontSize: 16.0,
47 | fontWeight: FontWeight.w600,
48 | );
49 | static TextStyle get button => GoogleFonts.poppins(
50 | fontSize: 14.0,
51 | fontWeight: FontWeight.w600,
52 | );
53 | static TextTheme get textTheme => TextTheme(
54 | headline1: headline1,
55 | headline2: headline2,
56 | headline3: headline3,
57 | bodyText1: bodytext1,
58 | caption: caption,
59 | );
60 | }
61 |
--------------------------------------------------------------------------------
/.github/workflows/db_backup.yml:
--------------------------------------------------------------------------------
1 | name: backup db
2 |
3 | on:
4 | schedule:
5 | - cron: "0 6 * * 1" # on 12:00 PM UTC+5:30 every Monday
6 | workflow_dispatch:
7 |
8 | jobs:
9 | build:
10 | runs-on: ubuntu-latest
11 | steps:
12 | - uses: actions/checkout@v3
13 | with:
14 | token: ${{ secrets.PAT }}
15 | - name: checkout repo content
16 | uses: actions/checkout@v2 # checkout the repository content to github runner
17 |
18 | - name: setup python
19 | uses: actions/setup-python@v4
20 | with:
21 | python-version: "3.9" # install the python version needed
22 |
23 | - name: install python packages
24 | run: |
25 | cd ./server
26 | python -m pip install --upgrade pip
27 | pip install -r requirements.txt
28 |
29 | - name: execute py script # run main.py
30 | env:
31 | MASTER_KEY: ${{ secrets.MASTER_KEY }}
32 | FIREBASE_KEY: ${{ secrets.FIREBASE_KEY }}
33 | run: |
34 | cd ./server
35 | python checkup_db.py
36 | python backup.py
37 |
38 | - name: create orphan # create orphan branch without deleting server/sunday.json
39 | run: |
40 | git add server/sunday.json
41 | git -c user.name='github-actions[bot]' -c user.email='41898282+github-actions[bot]@users.noreply.github.com' commit -m "backup" --no-verify --signoff
42 |
43 | git checkout --orphan backup
44 | git rm -rf .
45 | git clean -df
46 | git checkout master server/sunday.json
47 | - name: configure git # configure git
48 | run: |
49 | git config --global user.name "github-actions[bot]"
50 | git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
51 |
52 | - name: commit and push # commit and push the changes to the orphan branch
53 | run: |
54 | git add server/sunday.json
55 | git -c user.name='github-actions[bot]' -c user.email='41898282+github-actions[bot]@users.noreply.github.com' commit -m "backup" --no-verify --signoff
56 | git push origin backup --force
57 |
--------------------------------------------------------------------------------
/lib/ui/my_theme.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | import 'app_colors.dart';
4 | import 'text_styles.dart';
5 |
6 | class MyTheme {
7 | static ThemeData get ligthTheme {
8 | return ThemeData(
9 | primarySwatch: AppColors.createMaterialColor(AppColors.primaryColor),
10 | colorScheme: AppColors.lightScheme,
11 | fontFamily: AppTextStyle.fontFamily,
12 | textTheme: AppTextStyle.textTheme,
13 | cardTheme: const CardTheme(
14 | color: Colors.white,
15 | ),
16 | bottomNavigationBarTheme: BottomNavigationBarThemeData(
17 | unselectedItemColor: Colors.grey.shade500,
18 | selectedItemColor: AppColors.lightScheme.primary,
19 | ),
20 | inputDecorationTheme: InputDecorationTheme(
21 | border: OutlineInputBorder(borderRadius: BorderRadius.circular(16)),
22 | fillColor: Colors.grey.shade300,
23 | ),
24 | bottomSheetTheme: const BottomSheetThemeData(backgroundColor: Colors.transparent));
25 | }
26 |
27 | // on DarkMode the Swatch parameter is not working
28 | // https://github.com/flutter/flutter/issues/19089
29 | static ThemeData get darkTheme {
30 | return ThemeData(
31 | primarySwatch: AppColors.createMaterialColor(AppColors.primaryColor),
32 | colorScheme: AppColors.darkScheme,
33 | toggleableActiveColor: AppColors.darkScheme.secondary,
34 | // this can all be copied, waiting for verification
35 | fontFamily: AppTextStyle.fontFamily,
36 | textTheme: AppTextStyle.textTheme.copyWith(
37 | bodyText1: AppTextStyle.bodytext1.copyWith(
38 | color: Colors.white70,
39 | ),
40 | ),
41 | bottomNavigationBarTheme: BottomNavigationBarThemeData(
42 | unselectedItemColor: Colors.grey.shade400,
43 | selectedItemColor: AppColors.lightScheme.primary,
44 | ),
45 | // copy from ligthTheme
46 | inputDecorationTheme: ligthTheme.inputDecorationTheme,
47 | bottomSheetTheme: const BottomSheetThemeData(backgroundColor: Colors.transparent),
48 | bottomAppBarTheme: const BottomAppBarTheme(color: Colors.transparent),
49 | cardColor: AppColors.accentColor,
50 | );
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/server/main.py:
--------------------------------------------------------------------------------
1 | import os
2 | from dotenv import load_dotenv
3 | import build_new_item
4 | import requests
5 | import json
6 | import meilisearch
7 |
8 |
9 | load_dotenv()
10 | meiliClient = meilisearch.Client(
11 | "https://meilisearch-on-koyeb-imsudip.koyeb.app/", os.getenv('MASTER_KEY'))
12 | firebase_key = os.getenv('FIREBASE_KEY')
13 |
14 |
15 | def check_item_exists(video_id) -> bool:
16 | index = meiliClient.get_index('sunday')
17 | search = index.search(" ", {"filter": f"video_id = {video_id}"})
18 | if search['estimatedTotalHits'] > 0:
19 | return True
20 | else:
21 | return False
22 |
23 |
24 | def send_notification(song_data):
25 | print('Sending notification...')
26 | url = 'https://fcm.googleapis.com/fcm/send'
27 | not_data = {
28 | "to": "/topics/news",
29 | "notification": {
30 | "title": song_data["title"],
31 | "body": "Listen to this week's Sunday Suspense! 😱",
32 | },
33 | }
34 | headers = {"Content-Type": "application/json",
35 | "Authorization": firebase_key}
36 | response = requests.post(url, data=json.dumps(not_data), headers=headers)
37 | print(response.text)
38 |
39 |
40 | def update_db():
41 | playlist_url = 'https://api.rss2json.com/v1/api.json?rss_url=https%3A%2F%2Fwww.youtube.com%2Ffeeds%2Fvideos.xml%3Fplaylist_id%3DPLq71IJk8mCV4-DqsZ7W6zRS7uzKOmmT8j'
42 | response = requests.get(playlist_url)
43 | data = response.json()
44 | count = 0
45 | new_items = []
46 | for item in data['items']:
47 | video_id = item['link'].split('=')[1]
48 | link = 'https://www.youtube.com/watch?v=' + video_id
49 | if not check_item_exists(video_id):
50 | print('New item found!')
51 | print('Building new item...')
52 | new_item = build_new_item.getVideoDataFromLink(link)
53 | new_items.append(new_item)
54 | count += 1
55 |
56 | print(f'{count} new items added!')
57 | print(new_items)
58 | if count > 0:
59 | index = meiliClient.get_index('sunday')
60 | index.add_documents(new_items)
61 | send_notification(new_items[0])
62 | return
63 |
64 |
65 | if __name__ == "__main__":
66 | update_db()
67 |
68 | # cron job
69 | # every 4 hours on every sunday
70 | # 0 */4 * * 0 python3
71 |
--------------------------------------------------------------------------------
/ios/Runner/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | def localProperties = new Properties()
2 | def localPropertiesFile = rootProject.file('local.properties')
3 | if (localPropertiesFile.exists()) {
4 | localPropertiesFile.withReader('UTF-8') { reader ->
5 | localProperties.load(reader)
6 | }
7 | }
8 |
9 | def flutterRoot = localProperties.getProperty('flutter.sdk')
10 | if (flutterRoot == null) {
11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
12 | }
13 |
14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
15 | if (flutterVersionCode == null) {
16 | flutterVersionCode = '1'
17 | }
18 |
19 | def flutterVersionName = localProperties.getProperty('flutter.versionName')
20 | if (flutterVersionName == null) {
21 | flutterVersionName = '1.0'
22 | }
23 |
24 | apply plugin: 'com.android.application'
25 | apply plugin: 'kotlin-android'
26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
27 | apply plugin: 'com.google.gms.google-services'
28 |
29 | android {
30 | compileSdkVersion 33
31 | ndkVersion flutter.ndkVersion
32 |
33 | compileOptions {
34 | sourceCompatibility JavaVersion.VERSION_1_8
35 | targetCompatibility JavaVersion.VERSION_1_8
36 | }
37 |
38 | kotlinOptions {
39 | jvmTarget = '1.8'
40 | }
41 |
42 | sourceSets {
43 | main.java.srcDirs += 'src/main/kotlin'
44 | }
45 |
46 | defaultConfig {
47 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
48 | applicationId "com.example.sunday_suspense"
49 | // You can update the following values to match your application needs.
50 | // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration.
51 | minSdkVersion 19
52 | targetSdkVersion flutter.targetSdkVersion
53 | versionCode flutterVersionCode.toInteger()
54 | versionName flutterVersionName
55 | multiDexEnabled true
56 | }
57 |
58 | buildTypes {
59 | release {
60 | // TODO: Add your own signing config for the release build.
61 | // Signing with the debug keys for now, so `flutter run --release` works.
62 | signingConfig signingConfigs.debug
63 | }
64 | }
65 | }
66 |
67 | flutter {
68 | source '../..'
69 | }
70 |
71 | dependencies {
72 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
73 | }
74 |
--------------------------------------------------------------------------------
/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
11 |
19 |
23 |
27 |
28 |
29 |
30 |
31 |
32 |
34 |
37 |
38 |
41 |
42 |
43 |
44 |
45 |
46 |
48 |
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/lib/screens/historypage.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:get_storage/get_storage.dart';
3 | import '../services/database_service.dart';
4 | import '../ui/text_styles.dart';
5 | import '../widgets/song_viewers.dart';
6 |
7 | import '../ui/app_colors.dart';
8 |
9 | class HistoryPageScreen extends StatefulWidget {
10 | const HistoryPageScreen({super.key});
11 |
12 | @override
13 | State createState() => _HistoryPageScreenState();
14 | }
15 |
16 | class _HistoryPageScreenState extends State {
17 | List history = [];
18 |
19 | final box = GetStorage('HistoryBox');
20 |
21 | @override
22 | void initState() {
23 | box.listen(() {
24 | if (mounted) {
25 | setState(() {});
26 | if (history.length != box.getKeys().length) {
27 | DatabaseService.getAudioFromList(box.getKeys().map((e) => e.toString()).toList()).then((value) {
28 | setState(() {
29 | history = value;
30 | });
31 | });
32 | }
33 | }
34 | });
35 | DatabaseService.getAudioFromList(box.getKeys().map((e) => e.toString()).toList()).then((value) {
36 | setState(() {
37 | history = value;
38 | });
39 | });
40 | // print(box.getKeys());
41 | super.initState();
42 | }
43 |
44 | @override
45 | Widget build(BuildContext context) {
46 | return Scaffold(
47 | backgroundColor: AppColors.backgroundColor,
48 | body: SafeArea(
49 | child: Padding(
50 | padding: const EdgeInsets.symmetric(horizontal: 20),
51 | child: Column(
52 | crossAxisAlignment: CrossAxisAlignment.center,
53 | children: [
54 | const SizedBox(height: 20),
55 | Text(
56 | "History",
57 | style: AppTextStyle.headline2,
58 | ),
59 | const SizedBox(height: 20),
60 | Expanded(
61 | child: ListView.builder(
62 | itemBuilder: (context, index) {
63 | return MinimalVerticalListCard(
64 | songs: history,
65 | index: index,
66 | history: Duration(
67 | seconds: box.read(history[index]['video_id']),
68 | ),
69 | );
70 | },
71 | itemCount: history.length,
72 | )),
73 | ],
74 | ),
75 | ),
76 | ),
77 | );
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/lib/screens/root.dart:
--------------------------------------------------------------------------------
1 | import 'package:dot_navigation_bar/dot_navigation_bar.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:iconsax/iconsax.dart';
4 | import 'historypage.dart';
5 | import 'categorypage.dart';
6 | import 'homepage.dart';
7 | import '../ui/app_colors.dart';
8 | import '../widgets/art_glass_overlay.dart';
9 |
10 | import '../widgets/miniplayer.dart';
11 |
12 | class RootWidget extends StatefulWidget {
13 | const RootWidget({super.key});
14 |
15 | @override
16 | State createState() => _RootWidgetState();
17 | }
18 |
19 | class _RootWidgetState extends State {
20 | int _selectedIndex = 0;
21 | final List _widgetOptions = [
22 | const HomePageScreen(),
23 | const CategoryPageScreen(),
24 | const HistoryPageScreen()
25 | ];
26 | @override
27 | Widget build(BuildContext context) {
28 | return Scaffold(
29 | body: IndexedStack(
30 | index: _selectedIndex,
31 | children: _widgetOptions,
32 | ),
33 | backgroundColor: AppColors.backgroundColor,
34 | bottomNavigationBar: ArtGlassSmall(
35 | child: Column(
36 | mainAxisSize: MainAxisSize.min,
37 | children: [
38 | const MiniPlayer(),
39 | DotNavigationBar(
40 | currentIndex: _selectedIndex,
41 | onTap: (index) => setState(() {
42 | _selectedIndex = index;
43 | }),
44 | marginR: const EdgeInsets.symmetric(vertical: 8),
45 | paddingR: EdgeInsets.symmetric(horizontal: MediaQuery.of(context).size.width * 0.2),
46 | // enableFloatingNavBar: false,
47 | backgroundColor: Colors.transparent,
48 | items: [
49 | DotNavigationBarItem(
50 | icon: const Icon(Iconsax.home),
51 | selectedColor: AppColors.primaryWhiteColor,
52 | unselectedColor: AppColors.textSecondaryColor,
53 | ),
54 | DotNavigationBarItem(
55 | icon: const Icon(Iconsax.category),
56 | selectedColor: AppColors.primaryWhiteColor,
57 | unselectedColor: AppColors.textSecondaryColor,
58 | ),
59 | DotNavigationBarItem(
60 | icon: const Icon(Iconsax.save_2),
61 | selectedColor: AppColors.primaryWhiteColor,
62 | unselectedColor: AppColors.textSecondaryColor,
63 | ),
64 | ],
65 | ),
66 | ],
67 | ),
68 | ),
69 | );
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/lib/widgets/miniplayer.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/cupertino.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:get/get.dart';
4 | import '../ui/text_styles.dart';
5 | import 'player_parts.dart';
6 |
7 | import '../page_manager.dart';
8 | import '../screens/player.dart';
9 | import '../services/service_locator.dart';
10 |
11 | class MiniPlayer extends StatelessWidget {
12 | const MiniPlayer({super.key});
13 |
14 | @override
15 | Widget build(BuildContext context) {
16 | final pageManager = getIt();
17 | return ValueListenableBuilder(
18 | valueListenable: pageManager.currentSongTitleNotifier,
19 | builder: (_, title, __) {
20 | // print('title: $title');
21 | if (title == '') {
22 | return Container(
23 | height: 0,
24 | );
25 | } else {
26 | return GestureDetector(
27 | onTap: () {
28 | Get.to(() => PlayerScreen());
29 | },
30 | onVerticalDragStart: (details) {
31 | Get.to(() => PlayerScreen());
32 | },
33 | child: ClipRRect(
34 | borderRadius: const BorderRadius.vertical(top: Radius.circular(12)),
35 | child: SizedBox(
36 | height: 68,
37 | // color: AppColors.accentColor,
38 | child: Column(
39 | children: [
40 | const SizedBox(height: 2),
41 | const MinimalAudioProgressBar(),
42 | // const SizedBox(height: 10),
43 | Expanded(
44 | child: Row(
45 | crossAxisAlignment: CrossAxisAlignment.center,
46 | children: [
47 | const SizedBox(
48 | width: 16,
49 | ),
50 | ClipRRect(
51 | borderRadius: BorderRadius.circular(12),
52 | child: SizedBox(height: 60, child: const CurrentSongArt(width: 60)),
53 | ),
54 | const SizedBox(
55 | width: 16,
56 | ),
57 | Expanded(
58 | child: Text(
59 | title,
60 | style: AppTextStyle.bodytext1.copyWith(fontSize: 14),
61 | maxLines: 2,
62 | )),
63 | const SizedBox(
64 | width: 10,
65 | ),
66 | const AudioControlButtons(),
67 | const SizedBox(
68 | width: 16,
69 | ),
70 | ],
71 | )),
72 | // const SizedBox(height: 10),
73 | ],
74 | )),
75 | ),
76 | );
77 | }
78 | },
79 | );
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images": [
3 | {
4 | "filename": "Icon-App-20x20@2x.png",
5 | "idiom": "iphone",
6 | "scale": "2x",
7 | "size": "20x20"
8 | },
9 | {
10 | "filename": "Icon-App-20x20@3x.png",
11 | "idiom": "iphone",
12 | "scale": "3x",
13 | "size": "20x20"
14 | },
15 | {
16 | "filename": "Icon-App-29x29@1x.png",
17 | "idiom": "iphone",
18 | "scale": "1x",
19 | "size": "29x29"
20 | },
21 | {
22 | "filename": "Icon-App-29x29@2x.png",
23 | "idiom": "iphone",
24 | "scale": "2x",
25 | "size": "29x29"
26 | },
27 | {
28 | "filename": "Icon-App-29x29@3x.png",
29 | "idiom": "iphone",
30 | "scale": "3x",
31 | "size": "29x29"
32 | },
33 | {
34 | "filename": "Icon-App-40x40@2x.png",
35 | "idiom": "iphone",
36 | "scale": "2x",
37 | "size": "40x40"
38 | },
39 | {
40 | "filename": "Icon-App-40x40@3x.png",
41 | "idiom": "iphone",
42 | "scale": "3x",
43 | "size": "40x40"
44 | },
45 | {
46 | "filename": "Icon-App-60x60@2x.png",
47 | "idiom": "iphone",
48 | "scale": "2x",
49 | "size": "60x60"
50 | },
51 | {
52 | "filename": "Icon-App-60x60@3x.png",
53 | "idiom": "iphone",
54 | "scale": "3x",
55 | "size": "60x60"
56 | },
57 | {
58 | "filename": "Icon-App-20x20@1x.png",
59 | "idiom": "ipad",
60 | "scale": "1x",
61 | "size": "20x20"
62 | },
63 | {
64 | "filename": "Icon-App-20x20@2x.png",
65 | "idiom": "ipad",
66 | "scale": "2x",
67 | "size": "20x20"
68 | },
69 | {
70 | "filename": "Icon-App-29x29@1x.png",
71 | "idiom": "ipad",
72 | "scale": "1x",
73 | "size": "29x29"
74 | },
75 | {
76 | "filename": "Icon-App-29x29@2x.png",
77 | "idiom": "ipad",
78 | "scale": "2x",
79 | "size": "29x29"
80 | },
81 | {
82 | "filename": "Icon-App-40x40@1x.png",
83 | "idiom": "ipad",
84 | "scale": "1x",
85 | "size": "40x40"
86 | },
87 | {
88 | "filename": "Icon-App-40x40@2x.png",
89 | "idiom": "ipad",
90 | "scale": "2x",
91 | "size": "40x40"
92 | },
93 | {
94 | "filename": "Icon-App-76x76@1x.png",
95 | "idiom": "ipad",
96 | "scale": "1x",
97 | "size": "76x76"
98 | },
99 | {
100 | "filename": "Icon-App-76x76@2x.png",
101 | "idiom": "ipad",
102 | "scale": "2x",
103 | "size": "76x76"
104 | },
105 | {
106 | "filename": "Icon-App-83.5x83.5@2x.png",
107 | "idiom": "ipad",
108 | "scale": "2x",
109 | "size": "83.5x83.5"
110 | },
111 | {
112 | "filename": "Icon-App-1024x1024@1x.png",
113 | "idiom": "ios-marketing",
114 | "scale": "1x",
115 | "size": "1024x1024"
116 | }
117 | ],
118 | "info": {
119 | "author": "icons_launcher",
120 | "version": 1
121 | }
122 | }
--------------------------------------------------------------------------------
/linux/flutter/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # This file controls Flutter-level build steps. It should not be edited.
2 | cmake_minimum_required(VERSION 3.10)
3 |
4 | set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral")
5 |
6 | # Configuration provided via flutter tool.
7 | include(${EPHEMERAL_DIR}/generated_config.cmake)
8 |
9 | # TODO: Move the rest of this into files in ephemeral. See
10 | # https://github.com/flutter/flutter/issues/57146.
11 |
12 | # Serves the same purpose as list(TRANSFORM ... PREPEND ...),
13 | # which isn't available in 3.10.
14 | function(list_prepend LIST_NAME PREFIX)
15 | set(NEW_LIST "")
16 | foreach(element ${${LIST_NAME}})
17 | list(APPEND NEW_LIST "${PREFIX}${element}")
18 | endforeach(element)
19 | set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE)
20 | endfunction()
21 |
22 | # === Flutter Library ===
23 | # System-level dependencies.
24 | find_package(PkgConfig REQUIRED)
25 | pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
26 | pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0)
27 | pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0)
28 |
29 | set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so")
30 |
31 | # Published to parent scope for install step.
32 | set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE)
33 | set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE)
34 | set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE)
35 | set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE)
36 |
37 | list(APPEND FLUTTER_LIBRARY_HEADERS
38 | "fl_basic_message_channel.h"
39 | "fl_binary_codec.h"
40 | "fl_binary_messenger.h"
41 | "fl_dart_project.h"
42 | "fl_engine.h"
43 | "fl_json_message_codec.h"
44 | "fl_json_method_codec.h"
45 | "fl_message_codec.h"
46 | "fl_method_call.h"
47 | "fl_method_channel.h"
48 | "fl_method_codec.h"
49 | "fl_method_response.h"
50 | "fl_plugin_registrar.h"
51 | "fl_plugin_registry.h"
52 | "fl_standard_message_codec.h"
53 | "fl_standard_method_codec.h"
54 | "fl_string_codec.h"
55 | "fl_value.h"
56 | "fl_view.h"
57 | "flutter_linux.h"
58 | )
59 | list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/")
60 | add_library(flutter INTERFACE)
61 | target_include_directories(flutter INTERFACE
62 | "${EPHEMERAL_DIR}"
63 | )
64 | target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}")
65 | target_link_libraries(flutter INTERFACE
66 | PkgConfig::GTK
67 | PkgConfig::GLIB
68 | PkgConfig::GIO
69 | )
70 | add_dependencies(flutter flutter_assemble)
71 |
72 | # === Flutter tool backend ===
73 | # _phony_ is a non-existent file to force this command to run every time,
74 | # since currently there's no way to get a full input/output list from the
75 | # flutter tool.
76 | add_custom_command(
77 | OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS}
78 | ${CMAKE_CURRENT_BINARY_DIR}/_phony_
79 | COMMAND ${CMAKE_COMMAND} -E env
80 | ${FLUTTER_TOOL_ENVIRONMENT}
81 | "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh"
82 | ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE}
83 | VERBATIM
84 | )
85 | add_custom_target(flutter_assemble DEPENDS
86 | "${FLUTTER_LIBRARY}"
87 | ${FLUTTER_LIBRARY_HEADERS}
88 | )
89 |
--------------------------------------------------------------------------------
/lib/firebase_options.dart:
--------------------------------------------------------------------------------
1 | // File generated by FlutterFire CLI.
2 | // ignore_for_file: lines_longer_than_80_chars, avoid_classes_with_only_static_members
3 | import 'package:firebase_core/firebase_core.dart' show FirebaseOptions;
4 | import 'package:flutter/foundation.dart'
5 | show defaultTargetPlatform, kIsWeb, TargetPlatform;
6 |
7 | /// Default [FirebaseOptions] for use with your Firebase apps.
8 | ///
9 | /// Example:
10 | /// ```dart
11 | /// import 'firebase_options.dart';
12 | /// // ...
13 | /// await Firebase.initializeApp(
14 | /// options: DefaultFirebaseOptions.currentPlatform,
15 | /// );
16 | /// ```
17 | class DefaultFirebaseOptions {
18 | static FirebaseOptions get currentPlatform {
19 | if (kIsWeb) {
20 | return web;
21 | }
22 | switch (defaultTargetPlatform) {
23 | case TargetPlatform.android:
24 | return android;
25 | case TargetPlatform.iOS:
26 | return ios;
27 | case TargetPlatform.macOS:
28 | return macos;
29 | case TargetPlatform.windows:
30 | throw UnsupportedError(
31 | 'DefaultFirebaseOptions have not been configured for windows - '
32 | 'you can reconfigure this by running the FlutterFire CLI again.',
33 | );
34 | case TargetPlatform.linux:
35 | throw UnsupportedError(
36 | 'DefaultFirebaseOptions have not been configured for linux - '
37 | 'you can reconfigure this by running the FlutterFire CLI again.',
38 | );
39 | default:
40 | throw UnsupportedError(
41 | 'DefaultFirebaseOptions are not supported for this platform.',
42 | );
43 | }
44 | }
45 |
46 | static const FirebaseOptions web = FirebaseOptions(
47 | apiKey: 'AIzaSyB-vkM-y5BI3hdLtgw_FWHPYWxrtjcG3V8',
48 | appId: '1:50945720064:web:48c3a1a486cdaa6cba3de5',
49 | messagingSenderId: '50945720064',
50 | projectId: 'sunday-suspense-14243',
51 | authDomain: 'sunday-suspense-14243.firebaseapp.com',
52 | storageBucket: 'sunday-suspense-14243.appspot.com',
53 | measurementId: 'G-CQDTDTPE5H',
54 | );
55 |
56 | static const FirebaseOptions android = FirebaseOptions(
57 | apiKey: 'AIzaSyAnCIzi6qKv1LJKmKhqR1GLu6fVqYsvVwg',
58 | appId: '1:50945720064:android:ca46877ec54f647cba3de5',
59 | messagingSenderId: '50945720064',
60 | projectId: 'sunday-suspense-14243',
61 | storageBucket: 'sunday-suspense-14243.appspot.com',
62 | );
63 |
64 | static const FirebaseOptions ios = FirebaseOptions(
65 | apiKey: 'AIzaSyBGsEz7Ab__YfMU_ejLtsSww7JP4nI8Qig',
66 | appId: '1:50945720064:ios:f5424ba3bfce633aba3de5',
67 | messagingSenderId: '50945720064',
68 | projectId: 'sunday-suspense-14243',
69 | storageBucket: 'sunday-suspense-14243.appspot.com',
70 | iosClientId: '50945720064-1a40ats3fthtkvi1p6in3ih89aj5dnkj.apps.googleusercontent.com',
71 | iosBundleId: 'com.example.sundaySuspense',
72 | );
73 |
74 | static const FirebaseOptions macos = FirebaseOptions(
75 | apiKey: 'AIzaSyBGsEz7Ab__YfMU_ejLtsSww7JP4nI8Qig',
76 | appId: '1:50945720064:ios:f5424ba3bfce633aba3de5',
77 | messagingSenderId: '50945720064',
78 | projectId: 'sunday-suspense-14243',
79 | storageBucket: 'sunday-suspense-14243.appspot.com',
80 | iosClientId: '50945720064-1a40ats3fthtkvi1p6in3ih89aj5dnkj.apps.googleusercontent.com',
81 | iosBundleId: 'com.example.sundaySuspense',
82 | );
83 | }
84 |
--------------------------------------------------------------------------------
/lib/widgets/art_glass_overlay.dart:
--------------------------------------------------------------------------------
1 | import 'dart:math';
2 | import 'dart:ui';
3 |
4 | import 'package:cached_network_image/cached_network_image.dart';
5 | import 'package:flutter/material.dart';
6 | import '../ui/app_colors.dart';
7 |
8 | import '../page_manager.dart';
9 | import '../services/service_locator.dart';
10 |
11 | class ArtGlass extends StatelessWidget {
12 | const ArtGlass(
13 | {super.key, required this.child, this.intensity = 0.0, this.backgroundColor = AppColors.backgroundColor});
14 | final Widget child;
15 | final double intensity;
16 | final Color backgroundColor;
17 |
18 | @override
19 | Widget build(BuildContext context) {
20 | final pageManager = getIt();
21 | return ValueListenableBuilder(
22 | valueListenable: pageManager.currentSongImageNotifier,
23 | builder: (_, art, __) {
24 | if (art == "") {
25 | return Container(
26 | child: child,
27 | );
28 | } else {
29 | return Stack(
30 | children: [
31 | Container(
32 | color: backgroundColor,
33 | ),
34 | Positioned(
35 | top: -25,
36 | bottom: max(MediaQuery.of(context).size.height * 0.5, 60),
37 | child: CachedNetworkImage(
38 | imageUrl: art,
39 | width: MediaQuery.of(context).size.width,
40 | fit: BoxFit.cover,
41 | ),
42 | ),
43 | Container(
44 | color: backgroundColor.withOpacity(intensity),
45 | ),
46 | BackdropFilter(filter: ImageFilter.blur(sigmaX: 100, sigmaY: 100), child: child),
47 | ],
48 | );
49 | }
50 | },
51 | );
52 | }
53 | }
54 |
55 | class ArtGlassSmall extends StatelessWidget {
56 | const ArtGlassSmall(
57 | {super.key, required this.child, this.intensity = 0.0, this.backgroundColor = AppColors.backgroundColor});
58 | final Widget child;
59 | final double intensity;
60 | final Color backgroundColor;
61 |
62 | @override
63 | Widget build(BuildContext context) {
64 | final pageManager = getIt();
65 | return ValueListenableBuilder(
66 | valueListenable: pageManager.currentSongImageNotifier,
67 | builder: (_, art, __) {
68 | if (art == "") {
69 | return SizedBox(
70 | height: 62,
71 | child: child,
72 | );
73 | } else {
74 | return SizedBox(
75 | height: 130,
76 | child: Stack(
77 | children: [
78 | Container(
79 | color: backgroundColor,
80 | ),
81 | Positioned(
82 | bottom: -25,
83 | top: 100,
84 | child: CachedNetworkImage(
85 | imageUrl: art,
86 | width: MediaQuery.of(context).size.width,
87 | fit: BoxFit.cover,
88 | ),
89 | ),
90 | Container(
91 | color: backgroundColor.withOpacity(intensity),
92 | ),
93 | BackdropFilter(filter: ImageFilter.blur(sigmaX: 100, sigmaY: 100), child: child),
94 | ],
95 | ),
96 | );
97 | }
98 | },
99 | );
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
37 |
38 |
39 |
40 |
41 |
42 |
52 |
54 |
60 |
61 |
62 |
63 |
69 |
71 |
77 |
78 |
79 |
80 |
82 |
83 |
86 |
87 |
88 |
--------------------------------------------------------------------------------
/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
37 |
38 |
39 |
40 |
41 |
42 |
52 |
54 |
60 |
61 |
62 |
63 |
69 |
71 |
77 |
78 |
79 |
80 |
82 |
83 |
86 |
87 |
88 |
--------------------------------------------------------------------------------
/server/build_new_item.py:
--------------------------------------------------------------------------------
1 | # {
2 | # "title": "The Cask of Amontillado - Edgar Allan Poe",
3 | # "video_id": "CziZzauAa5Y",
4 | # "date": "2022-09-11T00:00:00",
5 | # "url": "https://youtube.com/watch?v=CziZzauAa5Y",
6 | # "thumbnail": "https://i.ytimg.com/vi/CziZzauAa5Y/sddefault.jpg?v=631f040a",
7 | # "length": 2362,
8 | # "views": 507970,
9 | # "author": "Mirchi Bangla",
10 | # "description": "Mirchi Bangla presents Edgar Allan Poe's The Cask of Amontillado on Sunday Suspense\n\nDate of Broadcast - 11th September, 2022\n\nMontresor - Deep\nFortunato - Agni\n\nTranslated, Adapted and Directed by Pushpal\nProduction, Sound Design and Original Music - Pradyut\nPoster Design - Join the Dots\nExecutive Producer - Alto\n\nInterns\n\nArpan Chatterjee\nSaptanil Maji\nUtsa Dey\n\nEnjoy and stay connected with us!!\n\nSubscribe to us :\nhttp://bit.ly/SubscribeMirchiBangla\n\nLike us on Facebook\nhttps://www.facebook.com/MirchiBangla/\n\nFollow us on Instagram\nhttps://www.instagram.com/mirchibangla/",
11 | # "blurhash": "V34UvhD%EMyDIAs.aeWBofn$0K%g%1Mw%MM|ozt6WAbc",
12 | # "tags": [
13 | # "horror"
14 | # ],
15 | # "timestamp": 1662834600
16 | # },
17 |
18 | import requests
19 | import json
20 | import pytube
21 | import datetime
22 | import blurhash
23 | import io
24 | import checkplaylist
25 |
26 |
27 | def getBlurHashFromLink(url):
28 | img = requests.get(url).content
29 | img_io = io.BytesIO(img)
30 | blurString = blurhash.encode(img_io, 5, 4)
31 | return blurString
32 |
33 |
34 | def clean_up_title(title) -> str:
35 | wildcards = [
36 | "Mirchi 98.3",
37 | "Radio Mirchi",
38 | "Radio Mirchi 98.3",
39 | "Radio Mirchi 98.3 FM",
40 | "Sunday Suspense",
41 | "#SundaySuspense",
42 | "Mirchi Bangla",
43 | "Radio Mirchi Bangla",
44 | "#Sunday Suspense",
45 | "#Sunday Suspense",
46 | "98.3",
47 | "#SundayNonsense",
48 | ]
49 | # remove all invisible characters
50 | title = title.replace("\u200b", "")
51 |
52 | splits = title.split("|")
53 | # strip whitespaces
54 | splits = [x.strip() for x in splits]
55 | if len(splits) > 1:
56 | # check if any of the wildcards are present
57 | for wildcard in wildcards:
58 | if wildcard in splits:
59 | # remove the wildcard
60 | splits.remove(wildcard)
61 | # join the splits
62 | title = " - ".join(splits)
63 | # update the title
64 | return title
65 | else:
66 | sp2 = title.split("-")
67 | sp2 = [x.strip() for x in sp2]
68 | if len(sp2) > 1:
69 | for wildcard in wildcards:
70 | if wildcard in sp2:
71 | sp2.remove(wildcard)
72 | title = " - ".join(sp2)
73 | return title
74 | else:
75 | return title
76 |
77 |
78 | def getVideoDataFromLink(url):
79 | yt = pytube.YouTube(url)
80 | v = {
81 | "title": clean_up_title(yt.title),
82 | "video_id": yt.video_id,
83 | "date": yt.publish_date.isoformat(),
84 | "url": yt.watch_url,
85 | "thumbnail": yt.thumbnail_url,
86 | "length": yt.length,
87 | "views": yt.views,
88 | "author": yt.author,
89 | "description": yt.description,
90 | "blurhash": getBlurHashFromLink(yt.thumbnail_url),
91 | "tags": checkplaylist.check_playlist_inclusion(yt.video_id),
92 | "timestamp": int(datetime.datetime.timestamp(yt.publish_date))
93 | }
94 |
95 | return v
96 |
--------------------------------------------------------------------------------
/lib/screens/show_all_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:animated_icon_button/animated_icon_button.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:loadmore/loadmore.dart';
4 | import '../ui/app_colors.dart';
5 | import '../widgets/player_parts.dart';
6 | import '../widgets/song_viewers.dart';
7 |
8 | class ShowAllPage extends StatefulWidget {
9 | const ShowAllPage({super.key, required this.title, required this.future});
10 | final String title;
11 | // future func
12 | final Future Function(int page) future;
13 |
14 | @override
15 | State createState() => _ShowAllPageState();
16 | }
17 |
18 | class _ShowAllPageState extends State {
19 | final List _songs = [];
20 | int _page = 1;
21 | bool _hasMore = true;
22 |
23 | bool isExpanded = true;
24 |
25 | Future _loadMore() async {
26 | print("loading more");
27 | if (!_hasMore) return false;
28 | var songs = await widget.future(_page);
29 | if (songs.length < 10) {
30 | _hasMore = false;
31 | }
32 | setState(() {
33 | _songs.addAll(songs);
34 | _page++;
35 | });
36 | return true;
37 | }
38 |
39 | @override
40 | Widget build(BuildContext context) {
41 | return Scaffold(
42 | appBar: AppBar(
43 | title: Text(widget.title),
44 | backgroundColor: AppColors.backgroundColor,
45 | elevation: 0,
46 | actions: [
47 | AnimatedIconButton(
48 | onPressed: () {
49 | setState(() {
50 | isExpanded = !isExpanded;
51 | });
52 | },
53 | icons: const [
54 | AnimatedIconItem(
55 | icon: Icon(Icons.unfold_less_rounded),
56 | ),
57 | AnimatedIconItem(
58 | icon: Icon(Icons.unfold_more_rounded),
59 | ),
60 | ],
61 | ),
62 | ],
63 | ),
64 | backgroundColor: AppColors.backgroundColor,
65 | body: LoadMore(
66 | onLoadMore: _loadMore,
67 | whenEmptyLoad: true,
68 | isFinish: !_hasMore,
69 | delegate: MyLoadMoreDelegate(),
70 | child: ListView.builder(
71 | scrollDirection: Axis.vertical,
72 | itemCount: _songs.length,
73 | itemBuilder: (context, index) {
74 | if (isExpanded) {
75 | return VerticalListCard(
76 | songs: _songs,
77 | index: index,
78 | );
79 | } else {
80 | return Padding(
81 | padding: const EdgeInsets.symmetric(horizontal: 20),
82 | child: MinimalVerticalListCard(songs: _songs, index: index),
83 | );
84 | }
85 | },
86 | ),
87 | ),
88 | );
89 | }
90 | }
91 |
92 | class MyLoadMoreDelegate extends LoadMoreDelegate {
93 | @override
94 | Widget buildChild(LoadMoreStatus status, {LoadMoreTextBuilder builder = DefaultLoadMoreTextBuilder.english}) {
95 | switch (status) {
96 | case LoadMoreStatus.loading:
97 | return const Center(
98 | child: LoadingAnimation(),
99 | );
100 | case LoadMoreStatus.nomore:
101 | return const Center(
102 | child: Text('No more'),
103 | );
104 |
105 | case LoadMoreStatus.idle:
106 | return const Center(
107 | child: Text('Idle'),
108 | );
109 | default:
110 | return const Center(
111 | child: Text('Default'),
112 | );
113 | }
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing to this repository
2 |
3 | ## Getting started
4 |
5 | Before you begin:
6 | - This project is powered by Flutter. Make sure you have the latest version of Flutter.
7 | - Have you read the [code of conduct](CODE_OF_CONDUCT.md)?
8 | - Make sure to check if an [issue exists](https://github.com/imsudip/sunday_suspense/issues) already & see if the issue is assigned to anyone or not.
9 | - If no one is assigned you can start working on the issue.
10 | - Make sure to leave a comment stating that you are working on the issue.
11 |
12 | ### Issue already assigned to someone? Ask before starting
13 |
14 | If the issue is already assigned to someone, leave a comment asking how you can contribute. Please do not start working on your own without confirmation.
15 |
16 | ### Don't see your issue? Open one
17 |
18 | If you spot something new, open an issue using a [template](https://github.com/imsudip/sunday_suspense/issues/new/choose). We'll use the issue to have a conversation about the problem you want to fix.
19 |
20 | ### Ready to make a change? Fork the repo
21 |
22 | Fork using GitHub Desktop:
23 |
24 | - [Getting started with GitHub Desktop](https://docs.github.com/en/desktop/installing-and-configuring-github-desktop/getting-started-with-github-desktop) will guide you through setting up Desktop.
25 | - Once Desktop is set up, you can use it to [fork the repo](https://docs.github.com/en/desktop/contributing-and-collaborating-using-github-desktop/cloning-and-forking-repositories-from-github-desktop)!
26 |
27 | Fork using the command line:
28 |
29 | - [Fork the repo](https://docs.github.com/en/github/getting-started-with-github/fork-a-repo#fork-an-example-repository) so that you can make your changes without affecting the original project until you're ready to merge them.
30 |
31 | Fork with [GitHub Codespaces](https://github.com/features/codespaces):
32 |
33 | - [Fork, edit, and preview](https://docs.github.com/en/free-pro-team@latest/github/developing-online-with-codespaces/creating-a-codespace) using [GitHub Codespaces](https://github.com/features/codespaces) without having to install and run the project locally.
34 |
35 | ### Make your update:
36 | Make your changes to the file(s) you'd like to update.
37 |
38 | ### Open a pull request
39 | When you're done making changes and you'd like to propose them for review, open your PR (pull request). You can use the GitHub user interface for some small changes, like fixing a typo or updating a readme. You can also fork the repo and then clone it locally, to view changes and run your tests on your machine.
40 |
41 | ### Submit your PR & get it reviewed
42 | - Once you submit your PR, others from the Docs community will review it with you. The first thing you're going to want to do is a [self review](#self-review).
43 | - After that, we may have questions, check back on your PR to keep up with the conversation.
44 | - We may ask for changes to be made before a PR can be merged. You can make any other changes in your fork, then commit them to your branch.
45 |
46 | ### Your PR is merged!
47 | Congratulations! The whole community thanks you. :sparkles:
48 |
49 | Once your PR is merged, you will be proudly listed as a contributor in the [contributor chart](https://github.com/imsudip/sunday_suspense/graphs/contributors).
50 |
51 | ### Self review
52 | You should always review your own PR first.
53 |
54 | For content changes, make sure that you:
55 | - [ ] Confirm the changes doesn't break anything else.
56 | - [ ] Compare your pull request's source changes to staging to confirm that the output matches the source and that everything is rendering as expected. This helps spot issues like typos, content that doesn't follow the style guide, or content that isn't rendering due to versioning problems.
57 | - [ ] Review the content for technical accuracy.
58 | - [ ] Copy-edit the changes for grammar or spelling mistakes.
59 |
--------------------------------------------------------------------------------
/linux/my_application.cc:
--------------------------------------------------------------------------------
1 | #include "my_application.h"
2 |
3 | #include
4 | #ifdef GDK_WINDOWING_X11
5 | #include
6 | #endif
7 |
8 | #include "flutter/generated_plugin_registrant.h"
9 |
10 | struct _MyApplication {
11 | GtkApplication parent_instance;
12 | char** dart_entrypoint_arguments;
13 | };
14 |
15 | G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION)
16 |
17 | // Implements GApplication::activate.
18 | static void my_application_activate(GApplication* application) {
19 | MyApplication* self = MY_APPLICATION(application);
20 | GtkWindow* window =
21 | GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application)));
22 |
23 | // Use a header bar when running in GNOME as this is the common style used
24 | // by applications and is the setup most users will be using (e.g. Ubuntu
25 | // desktop).
26 | // If running on X and not using GNOME then just use a traditional title bar
27 | // in case the window manager does more exotic layout, e.g. tiling.
28 | // If running on Wayland assume the header bar will work (may need changing
29 | // if future cases occur).
30 | gboolean use_header_bar = TRUE;
31 | #ifdef GDK_WINDOWING_X11
32 | GdkScreen* screen = gtk_window_get_screen(window);
33 | if (GDK_IS_X11_SCREEN(screen)) {
34 | const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen);
35 | if (g_strcmp0(wm_name, "GNOME Shell") != 0) {
36 | use_header_bar = FALSE;
37 | }
38 | }
39 | #endif
40 | if (use_header_bar) {
41 | GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new());
42 | gtk_widget_show(GTK_WIDGET(header_bar));
43 | gtk_header_bar_set_title(header_bar, "sunday_suspense");
44 | gtk_header_bar_set_show_close_button(header_bar, TRUE);
45 | gtk_window_set_titlebar(window, GTK_WIDGET(header_bar));
46 | } else {
47 | gtk_window_set_title(window, "sunday_suspense");
48 | }
49 |
50 | gtk_window_set_default_size(window, 1280, 720);
51 | gtk_widget_show(GTK_WIDGET(window));
52 |
53 | g_autoptr(FlDartProject) project = fl_dart_project_new();
54 | fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments);
55 |
56 | FlView* view = fl_view_new(project);
57 | gtk_widget_show(GTK_WIDGET(view));
58 | gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view));
59 |
60 | fl_register_plugins(FL_PLUGIN_REGISTRY(view));
61 |
62 | gtk_widget_grab_focus(GTK_WIDGET(view));
63 | }
64 |
65 | // Implements GApplication::local_command_line.
66 | static gboolean my_application_local_command_line(GApplication* application, gchar*** arguments, int* exit_status) {
67 | MyApplication* self = MY_APPLICATION(application);
68 | // Strip out the first argument as it is the binary name.
69 | self->dart_entrypoint_arguments = g_strdupv(*arguments + 1);
70 |
71 | g_autoptr(GError) error = nullptr;
72 | if (!g_application_register(application, nullptr, &error)) {
73 | g_warning("Failed to register: %s", error->message);
74 | *exit_status = 1;
75 | return TRUE;
76 | }
77 |
78 | g_application_activate(application);
79 | *exit_status = 0;
80 |
81 | return TRUE;
82 | }
83 |
84 | // Implements GObject::dispose.
85 | static void my_application_dispose(GObject* object) {
86 | MyApplication* self = MY_APPLICATION(object);
87 | g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev);
88 | G_OBJECT_CLASS(my_application_parent_class)->dispose(object);
89 | }
90 |
91 | static void my_application_class_init(MyApplicationClass* klass) {
92 | G_APPLICATION_CLASS(klass)->activate = my_application_activate;
93 | G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line;
94 | G_OBJECT_CLASS(klass)->dispose = my_application_dispose;
95 | }
96 |
97 | static void my_application_init(MyApplication* self) {}
98 |
99 | MyApplication* my_application_new() {
100 | return MY_APPLICATION(g_object_new(my_application_get_type(),
101 | "application-id", APPLICATION_ID,
102 | "flags", G_APPLICATION_NON_UNIQUE,
103 | nullptr));
104 | }
105 |
--------------------------------------------------------------------------------
/lib/services/database_service.dart:
--------------------------------------------------------------------------------
1 | import 'dart:math';
2 | import 'package:meilisearch/meilisearch.dart';
3 | import 'package:youtube_explode_dart/youtube_explode_dart.dart';
4 | import '../page_manager.dart';
5 | import '../widgets/song_viewers.dart';
6 | import 'service_locator.dart';
7 |
8 | class DatabaseService {
9 | DatabaseService();
10 | static buildQualityStore(List data) {
11 | final pageManager = getIt();
12 | var qualityStore = {};
13 | if (data.length >= 4) {
14 | qualityStore['Low'] = data[0]['url'];
15 | qualityStore['Medium'] = data[1]['url'];
16 | qualityStore['High'] = data[2]['url'];
17 | qualityStore['HD'] = data[3]['url'];
18 | } else if (data.length == 3) {
19 | qualityStore['Low'] = data[0]['url'];
20 | qualityStore['Medium'] = data[1]['url'];
21 | qualityStore['High'] = data[2]['url'];
22 | } else if (data.length == 2) {
23 | qualityStore['Low'] = data[0]['url'];
24 | qualityStore['Medium'] = data[1]['url'];
25 | } else if (data.length == 1) {
26 | qualityStore['Low'] = data[0]['url'];
27 | }
28 | pageManager.audioQualityStoreNotifier.value = qualityStore;
29 | var cuurentQuality = pageManager.audioQualityNotifier.value;
30 | if (qualityStore.containsKey(cuurentQuality)) {
31 | return qualityStore[cuurentQuality];
32 | } else {
33 | return qualityStore.values.last;
34 | }
35 | }
36 |
37 | static Future getStreamLink(String videoUrl) async {
38 | loadingDialog();
39 | var yt = YoutubeExplode();
40 | var videoId = videoUrl.split("v=")[1];
41 | var manifest = await yt.videos.streamsClient.getManifest(videoId);
42 | List