├── .firebaserc
├── .gitignore
├── .metadata
├── LICENSE
├── README.md
├── android
├── .project
├── .settings
│ └── org.eclipse.buildship.core.prefs
├── app
│ ├── .classpath
│ ├── .project
│ ├── .settings
│ │ └── org.eclipse.buildship.core.prefs
│ ├── build.gradle
│ └── src
│ │ └── main
│ │ ├── AndroidManifest.xml
│ │ ├── java
│ │ ├── com
│ │ │ └── example
│ │ │ │ └── domore
│ │ │ │ └── MainActivity.java
│ │ └── consulting
│ │ │ └── mabby
│ │ │ └── domore
│ │ │ └── MainActivity.java
│ │ └── res
│ │ ├── drawable
│ │ └── launch_background.xml
│ │ ├── mipmap-hdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-mdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xhdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xxhdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xxxhdpi
│ │ └── ic_launcher.png
│ │ └── values
│ │ └── styles.xml
├── build.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ │ └── gradle-wrapper.properties
└── settings.gradle
├── assets
├── animations
│ ├── loading_animation.flr
│ ├── loading_animation_looped.flr
│ └── loading_logo.flr
└── fonts
│ ├── IBMPlexSans-Bold.ttf
│ ├── IBMPlexSans-Light.ttf
│ ├── IBMPlexSans-Medium.ttf
│ ├── IBMPlexSans-Regular.ttf
│ └── IBMPlexSans-SemiBold.ttf
├── firebase.json
├── functions
├── package-lock.json
├── package.json
├── src
│ ├── generate_thumb.ts
│ ├── index.ts
│ └── pending_tasks_updater.ts
├── tsconfig.json
└── tslint.json
├── ios
├── Flutter
│ ├── AppFrameworkInfo.plist
│ ├── Debug.xcconfig
│ └── Release.xcconfig
├── Podfile
├── Runner.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ ├── IDEWorkspaceChecks.plist
│ │ │ └── WorkspaceSettings.xcsettings
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── Runner.xcscheme
├── Runner.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── WorkspaceSettings.xcsettings
└── Runner
│ ├── AppDelegate.h
│ ├── AppDelegate.m
│ ├── Assets.xcassets
│ ├── AppIcon.appiconset
│ │ ├── Contents.json
│ │ ├── Icon-App-1024x1024@1x.png
│ │ ├── 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-83.5x83.5@2x.png
│ └── LaunchImage.imageset
│ │ ├── Contents.json
│ │ ├── LaunchImage.png
│ │ ├── LaunchImage@2x.png
│ │ ├── LaunchImage@3x.png
│ │ └── README.md
│ ├── Base.lproj
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
│ ├── Info.plist
│ └── main.m
├── lib
├── main.dart
└── src
│ ├── App.dart
│ ├── blocs
│ ├── archive_bloc.dart
│ ├── event_bloc.dart
│ ├── events_bloc.dart
│ ├── home_bloc.dart
│ ├── new_event_bloc.dart
│ ├── new_image_bloc.dart
│ └── task_bloc.dart
│ ├── mixins
│ ├── tile_mixin.dart
│ └── upload_status_mixin.dart
│ ├── models
│ ├── event_model.dart
│ ├── summary_model.dart
│ ├── task_model.dart
│ └── user_model.dart
│ ├── resources
│ ├── firebase_storage_provider.dart
│ ├── firestore_provider.dart
│ └── google_sign_in_provider.dart
│ ├── screens
│ ├── archive_screen.dart
│ ├── event_screen.dart
│ ├── events_screen.dart
│ ├── gallery_screen.dart
│ ├── home_screen.dart
│ ├── initial_loading_screen.dart
│ ├── login_screen.dart
│ ├── new_event_screen.dart
│ ├── new_image_screen.dart
│ └── task_screen.dart
│ ├── services
│ ├── auth_service.dart
│ └── upload_status_service.dart
│ ├── utils.dart
│ └── widgets
│ ├── action_button.dart
│ ├── app_bar.dart
│ ├── async_image.dart
│ ├── async_thumbnail.dart
│ ├── avatar.dart
│ ├── big_text_input.dart
│ ├── carousel.dart
│ ├── event_dropdown.dart
│ ├── event_list_tile.dart
│ ├── fractionally_screen_sized_box.dart
│ ├── gradient_touchable_container.dart
│ ├── home_app_bar.dart
│ ├── loading_indicator.dart
│ ├── logo.dart
│ ├── new_item_dialog_button.dart
│ ├── new_item_dialog_route.dart
│ ├── ocurrance_selector.dart
│ ├── populated_drawer.dart
│ ├── priority_selector.dart
│ ├── search-box.dart
│ └── task_list_tile.dart
├── pubspec.yaml
└── test
└── src
├── resources
├── firestore_provider_test.dart
└── google_sign_in_provider_test.dart
└── utils_test.dart
/.firebaserc:
--------------------------------------------------------------------------------
1 | {
2 | "projects": {
3 | "default": "do-more-app"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.lock
4 | *.log
5 | *.pyc
6 | *.swp
7 | .DS_Store
8 | .atom/
9 | .buildlog/
10 | .history
11 | .svn/
12 |
13 | # IntelliJ related
14 | *.iml
15 | *.ipr
16 | *.iws
17 | .idea/
18 |
19 | # Visual Studio Code related
20 | .vscode/
21 |
22 | # Flutter/Dart/Pub related
23 | **/doc/api/
24 | .dart_tool/
25 | .flutter-plugins
26 | .packages
27 | .pub-cache/
28 | .pub/
29 | build/
30 |
31 | # Android related
32 | **/android/**/gradle-wrapper.jar
33 | **/android/.gradle
34 | **/android/captures/
35 | **/android/gradlew
36 | **/android/gradlew.bat
37 | **/android/local.properties
38 | **/android/**/GeneratedPluginRegistrant.java
39 |
40 | # iOS/XCode related
41 | **/ios/**/*.mode1v3
42 | **/ios/**/*.mode2v3
43 | **/ios/**/*.moved-aside
44 | **/ios/**/*.pbxuser
45 | **/ios/**/*.perspectivev3
46 | **/ios/**/*sync/
47 | **/ios/**/.sconsign.dblite
48 | **/ios/**/.tags*
49 | **/ios/**/.vagrant/
50 | **/ios/**/DerivedData/
51 | **/ios/**/Icon?
52 | **/ios/**/Pods/
53 | **/ios/**/.symlinks/
54 | **/ios/**/profile
55 | **/ios/**/xcuserdata
56 | **/ios/.generated/
57 | **/ios/Flutter/App.framework
58 | **/ios/Flutter/Flutter.framework
59 | **/ios/Flutter/Generated.xcconfig
60 | **/ios/Flutter/app.flx
61 | **/ios/Flutter/app.zip
62 | **/ios/Flutter/flutter_assets/
63 | **/ios/ServiceDefinitions.json
64 | **/ios/Runner/GeneratedPluginRegistrant.*
65 |
66 | # Exceptions to above rules.
67 | !**/ios/**/default.mode1v3
68 | !**/ios/**/default.mode2v3
69 | !**/ios/**/default.pbxuser
70 | !**/ios/**/default.perspectivev3
71 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
72 |
73 | # Firebase api keys
74 | **/GoogleService-Info.plist
75 | **/google-services.json
76 |
77 |
78 | ## Compiled JavaScript files
79 | **/*.js
80 | **/*.js.map
81 |
82 | # Typescript v1 declaration files
83 | typings/
84 |
85 | node_modules/
--------------------------------------------------------------------------------
/.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 and should not be manually edited.
5 |
6 | version:
7 | revision: 5391447fae6209bb21a89e6a5a6583cac1af9b4b
8 | channel: stable
9 |
10 | project_type: app
11 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Mariano Uvalle
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # do_more (DO>) [](https://app.bitrise.io/app/11d283a1ca8ed38e)
2 |
3 | A glorified todo list with a beautiful ui.
4 |
5 | ## Login with Google
6 | 
7 |
8 | ## Events
9 | Organize your tasks by events, visualize them in their page and add new ones specifying their occurrence.
10 |
11 | 
12 |
13 | ## Tasks
14 | Add new tasks from the main screen, specify the event they belong to and their priority.
15 |
16 | 
17 |
18 | Filter your tasks by name or by event name.
19 |
20 | 
21 |
22 | Mark tasks as done and recover them from the archive section.
23 |
24 | 
25 |
26 | Edit tasks.
27 |
28 | 
29 |
30 | ## Media
31 | Add pictures from the main screen and link them to an event, both thumbnails and full-size images are locally cached for faster subsequent access.
32 |
33 | 
34 |
35 | Gallery screen for every event with thumbnails of all your images.
36 |
37 | 
38 |
39 | Full screen gallery.
40 |
41 | 
42 |
43 | ## Roadmap
44 |
45 | https://trello.com/b/zdKMw2JL/do
46 |
47 |
--------------------------------------------------------------------------------
/android/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | android
4 | Project android created by Buildship.
5 |
6 |
7 |
8 |
9 | org.eclipse.buildship.core.gradleprojectbuilder
10 |
11 |
12 |
13 |
14 |
15 | org.eclipse.buildship.core.gradleprojectnature
16 |
17 |
18 |
--------------------------------------------------------------------------------
/android/.settings/org.eclipse.buildship.core.prefs:
--------------------------------------------------------------------------------
1 | connection.project.dir=
2 | eclipse.preferences.version=1
3 |
--------------------------------------------------------------------------------
/android/app/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/android/app/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | app
4 | Project app created by Buildship.
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 | org.eclipse.buildship.core.gradleprojectbuilder
15 |
16 |
17 |
18 |
19 |
20 | org.eclipse.jdt.core.javanature
21 | org.eclipse.buildship.core.gradleprojectnature
22 |
23 |
24 |
--------------------------------------------------------------------------------
/android/app/.settings/org.eclipse.buildship.core.prefs:
--------------------------------------------------------------------------------
1 | connection.project.dir=..
2 | eclipse.preferences.version=1
3 |
--------------------------------------------------------------------------------
/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 from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
26 |
27 | android {
28 | compileSdkVersion 27
29 |
30 | lintOptions {
31 | disable 'InvalidPackage'
32 | }
33 |
34 | defaultConfig {
35 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
36 | applicationId "consulting.mabby.domore"
37 | minSdkVersion 21
38 | targetSdkVersion 27
39 | versionCode flutterVersionCode.toInteger()
40 | versionName flutterVersionName
41 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
42 | }
43 |
44 | buildTypes {
45 | release {
46 | // TODO: Add your own signing config for the release build.
47 | // Signing with the debug keys for now, so `flutter run --release` works.
48 | signingConfig signingConfigs.debug
49 | }
50 | }
51 | }
52 |
53 | flutter {
54 | source '../..'
55 | }
56 |
57 | dependencies {
58 | testImplementation 'junit:junit:4.12'
59 | androidTestImplementation 'com.android.support.test:runner:1.0.2'
60 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
61 | }
62 |
63 | apply plugin: 'com.google.gms.google-services'
64 |
--------------------------------------------------------------------------------
/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
8 |
9 |
10 |
15 |
19 |
26 |
30 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/android/app/src/main/java/com/example/domore/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.example.domore;
2 |
3 | import android.os.Bundle;
4 | import io.flutter.app.FlutterActivity;
5 | import io.flutter.plugins.GeneratedPluginRegistrant;
6 |
7 | public class MainActivity extends FlutterActivity {
8 | @Override
9 | protected void onCreate(Bundle savedInstanceState) {
10 | super.onCreate(savedInstanceState);
11 | GeneratedPluginRegistrant.registerWith(this);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/android/app/src/main/java/consulting/mabby/domore/MainActivity.java:
--------------------------------------------------------------------------------
1 | package consulting.mabby.domore;
2 |
3 | import android.os.Bundle;
4 | import io.flutter.app.FlutterActivity;
5 | import io.flutter.plugins.GeneratedPluginRegistrant;
6 |
7 | public class MainActivity extends FlutterActivity {
8 | @Override
9 | protected void onCreate(Bundle savedInstanceState) {
10 | super.onCreate(savedInstanceState);
11 | GeneratedPluginRegistrant.registerWith(this);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AYM1607/do_more/c415a2d1396e45facd11e6b60f2821424df99216/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AYM1607/do_more/c415a2d1396e45facd11e6b60f2821424df99216/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AYM1607/do_more/c415a2d1396e45facd11e6b60f2821424df99216/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AYM1607/do_more/c415a2d1396e45facd11e6b60f2821424df99216/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AYM1607/do_more/c415a2d1396e45facd11e6b60f2821424df99216/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | repositories {
3 | google()
4 | jcenter()
5 | }
6 |
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:3.2.1'
9 | classpath 'com.google.gms:google-services:3.2.1'
10 | }
11 | }
12 |
13 | allprojects {
14 | repositories {
15 | google()
16 | jcenter()
17 | }
18 | }
19 |
20 | rootProject.buildDir = '../build'
21 | subprojects {
22 | project.buildDir = "${rootProject.buildDir}/${project.name}"
23 | }
24 | subprojects {
25 | project.evaluationDependsOn(':app')
26 | }
27 |
28 | task clean(type: Delete) {
29 | delete rootProject.buildDir
30 | }
31 |
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1536M
2 |
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Fri Jun 23 08:50:38 CEST 2017
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip
7 |
--------------------------------------------------------------------------------
/android/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
3 | def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
4 |
5 | def plugins = new Properties()
6 | def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
7 | if (pluginsFile.exists()) {
8 | pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
9 | }
10 |
11 | plugins.each { name, path ->
12 | def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
13 | include ":$name"
14 | project(":$name").projectDir = pluginDirectory
15 | }
16 |
--------------------------------------------------------------------------------
/assets/animations/loading_animation.flr:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AYM1607/do_more/c415a2d1396e45facd11e6b60f2821424df99216/assets/animations/loading_animation.flr
--------------------------------------------------------------------------------
/assets/animations/loading_animation_looped.flr:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AYM1607/do_more/c415a2d1396e45facd11e6b60f2821424df99216/assets/animations/loading_animation_looped.flr
--------------------------------------------------------------------------------
/assets/animations/loading_logo.flr:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AYM1607/do_more/c415a2d1396e45facd11e6b60f2821424df99216/assets/animations/loading_logo.flr
--------------------------------------------------------------------------------
/assets/fonts/IBMPlexSans-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AYM1607/do_more/c415a2d1396e45facd11e6b60f2821424df99216/assets/fonts/IBMPlexSans-Bold.ttf
--------------------------------------------------------------------------------
/assets/fonts/IBMPlexSans-Light.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AYM1607/do_more/c415a2d1396e45facd11e6b60f2821424df99216/assets/fonts/IBMPlexSans-Light.ttf
--------------------------------------------------------------------------------
/assets/fonts/IBMPlexSans-Medium.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AYM1607/do_more/c415a2d1396e45facd11e6b60f2821424df99216/assets/fonts/IBMPlexSans-Medium.ttf
--------------------------------------------------------------------------------
/assets/fonts/IBMPlexSans-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AYM1607/do_more/c415a2d1396e45facd11e6b60f2821424df99216/assets/fonts/IBMPlexSans-Regular.ttf
--------------------------------------------------------------------------------
/assets/fonts/IBMPlexSans-SemiBold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AYM1607/do_more/c415a2d1396e45facd11e6b60f2821424df99216/assets/fonts/IBMPlexSans-SemiBold.ttf
--------------------------------------------------------------------------------
/firebase.json:
--------------------------------------------------------------------------------
1 | {
2 | "functions": {
3 | "predeploy": [
4 | "npm --prefix \"$RESOURCE_DIR\" run lint",
5 | "npm --prefix \"$RESOURCE_DIR\" run build"
6 | ]
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/functions/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "functions",
3 | "scripts": {
4 | "lint": "tslint --project tsconfig.json",
5 | "build": "tsc",
6 | "serve": "npm run build && firebase serve --only functions",
7 | "shell": "npm run build && firebase functions:shell",
8 | "start": "npm run shell",
9 | "deploy": "firebase deploy --only functions",
10 | "logs": "firebase functions:log"
11 | },
12 | "main": "lib/index.js",
13 | "dependencies": {
14 | "@google-cloud/storage": "^2.5.0",
15 | "@types/fs-extra": "^5.0.5",
16 | "@types/sharp": "^0.22.1",
17 | "firebase-admin": "~7.0.0",
18 | "firebase-functions": "^2.2.1",
19 | "fs-extra": "^7.0.1",
20 | "sharp": "^0.22.0"
21 | },
22 | "devDependencies": {
23 | "tslint": "^5.12.0",
24 | "typescript": "^3.2.2"
25 | },
26 | "private": true
27 | }
28 |
--------------------------------------------------------------------------------
/functions/src/generate_thumb.ts:
--------------------------------------------------------------------------------
1 | import * as functions from 'firebase-functions';
2 | import { Storage } from '@google-cloud/storage';
3 |
4 | const gcs = new Storage();
5 |
6 | import { tmpdir } from 'os';
7 | import { join, dirname } from 'path';
8 |
9 | import * as sharp from 'sharp';
10 | import * as fs from 'fs-extra';
11 |
12 | /// Creates a thumbnail for every image that gets uploaded to the storage bucket.
13 | export const generateThumb: functions.CloudFunction = functions.storage.object().onFinalize(async object => {
14 | // Find the bucket where the uploaded file resides.
15 | const bucket = gcs.bucket(object.bucket);
16 |
17 | // Find the path of the file inside the bucket.
18 | const filePathGcs = object.name;
19 |
20 | // Save the name of the file.
21 | const fileName = filePathGcs!.split('/').pop();
22 |
23 | // Directory where the file is stored inside the bucket.
24 | const bucketDirectory = dirname(filePathGcs!);
25 | const workingDirectory = join(tmpdir(), 'thumbnails');
26 | const tmpFilePath = join(workingDirectory, fileName!);
27 |
28 | if (fileName!.includes('thumb@') || !object.contentType!.includes('image')) {
29 | console.log('Exiting function, already compressed or no image.');
30 | return false;
31 | }
32 |
33 | // Ensure that our directory exists.
34 | await fs.ensureDir(workingDirectory);
35 |
36 | // Download the source file to the temporary directory.
37 | await bucket.file(filePathGcs!).download({
38 | destination: tmpFilePath,
39 | });
40 |
41 | // Create the thumnail in 124 size.
42 | const thumbnailName = `thumb@${fileName}`;
43 | const thumbnailLocalPath = join(workingDirectory, thumbnailName);
44 |
45 | await sharp(tmpFilePath)
46 | .resize(256, 256)
47 | .toFile(thumbnailLocalPath);
48 |
49 | // Upload the resulting thumnail to the same directory as the original file.
50 | await bucket.upload(thumbnailLocalPath, {
51 | destination: join(bucketDirectory, thumbnailName),
52 | });
53 | console.log('Thumbnail created successfully')
54 |
55 | // Exit the function deleting all the temprorary files.
56 | return fs.remove(workingDirectory);
57 | });
--------------------------------------------------------------------------------
/functions/src/index.ts:
--------------------------------------------------------------------------------
1 | import * as functions from 'firebase-functions';
2 |
3 | import { generateThumb } from './generate_thumb';
4 | import { pendingTasksUpdater } from './pending_tasks_updater';
5 |
6 | export const generate_thumb: functions.CloudFunction = generateThumb;
7 | export const pending_tasks_updater: functions.CloudFunction> = pendingTasksUpdater;
--------------------------------------------------------------------------------
/functions/src/pending_tasks_updater.ts:
--------------------------------------------------------------------------------
1 | import * as functions from 'firebase-functions';
2 | import * as admin from 'firebase-admin';
3 | import { DocumentSnapshot } from 'firebase-functions/lib/providers/firestore';
4 |
5 | type DocumentReference = admin.firestore.DocumentReference;
6 | type FieldValue = admin.firestore.FieldValue;
7 |
8 | admin.initializeApp();
9 |
10 |
11 | const incrementValue = admin.firestore.FieldValue.increment(1);
12 | const decrementValue = admin.firestore.FieldValue.increment(-1);
13 | const db = admin.firestore();
14 |
15 | /// Gets the user [DocumentReference] for the current task.
16 | const getUserReference = async (taskSnapShot: DocumentSnapshot) => {
17 | const querySnapshot = await db.collection('users').where('username', '==', taskSnapShot.get('ownerUsername')).get()
18 | return querySnapshot.docs[0].ref;
19 | }
20 |
21 | /// Gets an event document reference for the current task.
22 | const getEventReference = async (
23 | taskSnapshot: DocumentSnapshot,
24 | userReference: DocumentReference
25 | ) => {
26 | const querySnapshot = await userReference.collection('events').where('name', '==', taskSnapshot.get('event')).get();
27 | return querySnapshot.docs[0].ref;
28 | }
29 |
30 | /// Increments the necessary fields in the event and user documents linked to this task.
31 | const incrementFromPriority = async (
32 | priority: number,
33 | eventReference: DocumentReference,
34 | userReference: DocumentReference,
35 | value: FieldValue,
36 | ) => {
37 | let userFieldName: string = '';
38 | let eventFieldName: string = '';
39 |
40 | switch (priority) {
41 | case 0:
42 | userFieldName = 'pendingLow';
43 | eventFieldName = 'lowPriority';
44 | break;
45 | case 1:
46 | userFieldName = 'pendingMedium';
47 | eventFieldName = 'mediumPriority';
48 | break;
49 | case 2:
50 | userFieldName = 'pendingHigh';
51 | eventFieldName = 'highPriority';
52 | break;
53 | }
54 |
55 | await eventReference.update({ [eventFieldName]: value });
56 | await userReference.update({ [userFieldName]: value });
57 | }
58 |
59 | /// Incrementsj only the 'pendingTasks' field for the provided event.
60 | const incrementPendingTasks = async (
61 | eventReference: DocumentReference,
62 | value: FieldValue
63 | ) => {
64 | await eventReference.update({ 'pendingTasks': value });
65 | }
66 |
67 | export const pendingTasksUpdater: functions.CloudFunction> = functions.firestore
68 | .document('tasks/{taskId}')
69 | .onWrite(async (change, _) => {
70 | /// Snapshot of the document before the operation.
71 | ///
72 | /// Only applicable for update and delete operations.
73 | const before: DocumentSnapshot = change.before;
74 |
75 | /// Snapshot of the document after the operation.
76 | ///
77 | /// Only applicable for update and create operations.
78 | const after: DocumentSnapshot = change.after;
79 |
80 | /// Operation performed to the task.
81 | let action: string;
82 |
83 | /// Reference to the user dociment linked to this task.
84 | let userDocument: DocumentReference;
85 |
86 | /// Reference to the event document linked to this task before the operation.
87 | let eventDocument: DocumentReference;
88 |
89 | /// Reference to the event document linked to this task after the operation.
90 | let eventDocumentBefore: DocumentReference | null;
91 |
92 |
93 | if (change.after.exists && change.before.exists) {
94 | /// Exit the funciton if case this is an update operation and the
95 | /// event and priority of the taks haven't changed.
96 | if (before.get('priority') === after.get('priority') && before.get('event') === after.get('event') && before.get('done') === after.get('done')) {
97 | console.log('Nothing to update, exiting function');
98 | return true;
99 | }
100 | userDocument = await getUserReference(after);
101 | eventDocumentBefore = await getEventReference(before, userDocument);
102 | eventDocument = await getEventReference(after, userDocument);
103 | action = 'update';
104 | } else if (!change.before.exists) {
105 | userDocument = await getUserReference(after);
106 | eventDocument = await getEventReference(after, userDocument);
107 | action = 'create';
108 | } else {
109 | userDocument = await getUserReference(before);
110 | eventDocument = await getEventReference(before, userDocument);
111 | action = 'delete';
112 | }
113 |
114 | switch (action) {
115 | case 'create':
116 | await incrementFromPriority(after.get('priority'), eventDocument, userDocument, incrementValue);
117 | await incrementPendingTasks(eventDocument, incrementValue);
118 | break;
119 | case 'delete':
120 | await incrementFromPriority(before.get('priority'), eventDocument, userDocument, decrementValue);
121 | await incrementPendingTasks(eventDocument, decrementValue);
122 | break;
123 | case 'update':
124 | if (before.get('done') !== after.get('done')) {
125 | const value = after.get('done') ? decrementValue : incrementValue;
126 | await incrementFromPriority(after.get('priority'), eventDocument, userDocument, value);
127 | await incrementPendingTasks(eventDocument, value);
128 | }
129 | if (before.get('priority') !== after.get('priority')) {
130 | await incrementFromPriority(before.get('priority'), eventDocumentBefore!, userDocument, decrementValue);
131 | await incrementFromPriority(after.get('priority'), eventDocument, userDocument, incrementValue);
132 | }
133 | if (before.get('event') !== after.get('event')) {
134 | await incrementPendingTasks(eventDocumentBefore!, decrementValue);
135 | await incrementPendingTasks(eventDocument, incrementValue);
136 | }
137 | break;
138 | }
139 |
140 | console.log('Successfully updated user and event due to task update');
141 | return true;
142 | });
--------------------------------------------------------------------------------
/functions/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "noImplicitReturns": true,
5 | "noUnusedLocals": true,
6 | "outDir": "lib",
7 | "sourceMap": true,
8 | "strict": true,
9 | "target": "es2015"
10 | },
11 | "compileOnSave": true,
12 | "include": [
13 | "src"
14 | ]
15 | }
16 |
--------------------------------------------------------------------------------
/functions/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "rules": {
3 | // -- Strict errors --
4 | // These lint rules are likely always a good idea.
5 |
6 | // Force function overloads to be declared together. This ensures readers understand APIs.
7 | "adjacent-overload-signatures": true,
8 |
9 | // Do not allow the subtle/obscure comma operator.
10 | "ban-comma-operator": true,
11 |
12 | // Do not allow internal modules or namespaces . These are deprecated in favor of ES6 modules.
13 | "no-namespace": true,
14 |
15 | // Do not allow parameters to be reassigned. To avoid bugs, developers should instead assign new values to new vars.
16 | "no-parameter-reassignment": true,
17 |
18 | // Force the use of ES6-style imports instead of /// imports.
19 | "no-reference": true,
20 |
21 | // Do not allow type assertions that do nothing. This is a big warning that the developer may not understand the
22 | // code currently being edited (they may be incorrectly handling a different type case that does not exist).
23 | "no-unnecessary-type-assertion": true,
24 |
25 | // Disallow nonsensical label usage.
26 | "label-position": true,
27 |
28 | // Disallows the (often typo) syntax if (var1 = var2). Replace with if (var2) { var1 = var2 }.
29 | "no-conditional-assignment": true,
30 |
31 | // Disallows constructors for primitive types (e.g. new Number('123'), though Number('123') is still allowed).
32 | "no-construct": true,
33 |
34 | // Do not allow super() to be called twice in a constructor.
35 | "no-duplicate-super": true,
36 |
37 | // Do not allow the same case to appear more than once in a switch block.
38 | "no-duplicate-switch-case": true,
39 |
40 | // Do not allow a variable to be declared more than once in the same block. Consider function parameters in this
41 | // rule.
42 | "no-duplicate-variable": [true, "check-parameters"],
43 |
44 | // Disallows a variable definition in an inner scope from shadowing a variable in an outer scope. Developers should
45 | // instead use a separate variable name.
46 | "no-shadowed-variable": true,
47 |
48 | // Empty blocks are almost never needed. Allow the one general exception: empty catch blocks.
49 | "no-empty": [true, "allow-empty-catch"],
50 |
51 | // Functions must either be handled directly (e.g. with a catch() handler) or returned to another function.
52 | // This is a major source of errors in Cloud Functions and the team strongly recommends leaving this rule on.
53 | "no-floating-promises": true,
54 |
55 | // Do not allow any imports for modules that are not in package.json. These will almost certainly fail when
56 | // deployed.
57 | "no-implicit-dependencies": true,
58 |
59 | // The 'this' keyword can only be used inside of classes.
60 | "no-invalid-this": true,
61 |
62 | // Do not allow strings to be thrown because they will not include stack traces. Throw Errors instead.
63 | "no-string-throw": true,
64 |
65 | // Disallow control flow statements, such as return, continue, break, and throw in finally blocks.
66 | "no-unsafe-finally": true,
67 |
68 | // Do not allow variables to be used before they are declared.
69 | "no-use-before-declare": true,
70 |
71 | // Expressions must always return a value. Avoids common errors like const myValue = functionReturningVoid();
72 | "no-void-expression": [true, "ignore-arrow-function-shorthand"],
73 |
74 | // Disallow duplicate imports in the same file.
75 | "no-duplicate-imports": true,
76 |
77 |
78 | // -- Strong Warnings --
79 | // These rules should almost never be needed, but may be included due to legacy code.
80 | // They are left as a warning to avoid frustration with blocked deploys when the developer
81 | // understand the warning and wants to deploy anyway.
82 |
83 | // Warn when an empty interface is defined. These are generally not useful.
84 | "no-empty-interface": {"severity": "warning"},
85 |
86 | // Warn when an import will have side effects.
87 | "no-import-side-effect": {"severity": "warning"},
88 |
89 | // Warn when variables are defined with var. Var has subtle meaning that can lead to bugs. Strongly prefer const for
90 | // most values and let for values that will change.
91 | "no-var-keyword": {"severity": "warning"},
92 |
93 | // Prefer === and !== over == and !=. The latter operators support overloads that are often accidental.
94 | "triple-equals": {"severity": "warning"},
95 |
96 | // Warn when using deprecated APIs.
97 | "deprecation": {"severity": "warning"},
98 |
99 | // -- Light Warnings --
100 | // These rules are intended to help developers use better style. Simpler code has fewer bugs. These would be "info"
101 | // if TSLint supported such a level.
102 |
103 | // prefer for( ... of ... ) to an index loop when the index is only used to fetch an object from an array.
104 | // (Even better: check out utils like .map if transforming an array!)
105 | "prefer-for-of": {"severity": "warning"},
106 |
107 | // Warns if function overloads could be unified into a single function with optional or rest parameters.
108 | "unified-signatures": {"severity": "warning"},
109 |
110 | // Prefer const for values that will not change. This better documents code.
111 | "prefer-const": {"severity": "warning"},
112 |
113 | // Multi-line object literals and function calls should have a trailing comma. This helps avoid merge conflicts.
114 | "trailing-comma": {"severity": "warning"}
115 | },
116 |
117 | "defaultSeverity": "error"
118 | }
119 |
--------------------------------------------------------------------------------
/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 | 8.0
25 |
26 |
27 |
--------------------------------------------------------------------------------
/ios/Flutter/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
2 | #include "Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
2 | #include "Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/ios/Podfile:
--------------------------------------------------------------------------------
1 | # Uncomment this line to define a global platform for your project
2 | # platform :ios, '9.0'
3 |
4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency.
5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true'
6 |
7 | project 'Runner', {
8 | 'Debug' => :debug,
9 | 'Profile' => :release,
10 | 'Release' => :release,
11 | }
12 |
13 | def parse_KV_file(file, separator='=')
14 | file_abs_path = File.expand_path(file)
15 | if !File.exists? file_abs_path
16 | return [];
17 | end
18 | pods_ary = []
19 | skip_line_start_symbols = ["#", "/"]
20 | File.foreach(file_abs_path) { |line|
21 | next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ }
22 | plugin = line.split(pattern=separator)
23 | if plugin.length == 2
24 | podname = plugin[0].strip()
25 | path = plugin[1].strip()
26 | podpath = File.expand_path("#{path}", file_abs_path)
27 | pods_ary.push({:name => podname, :path => podpath});
28 | else
29 | puts "Invalid plugin specification: #{line}"
30 | end
31 | }
32 | return pods_ary
33 | end
34 |
35 | target 'Runner' do
36 | # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock
37 | # referring to absolute paths on developers' machines.
38 | system('rm -rf .symlinks')
39 | system('mkdir -p .symlinks/plugins')
40 |
41 | # Flutter Pods
42 | generated_xcode_build_settings = parse_KV_file('./Flutter/Generated.xcconfig')
43 | if generated_xcode_build_settings.empty?
44 | puts "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter packages get is executed first."
45 | end
46 | generated_xcode_build_settings.map { |p|
47 | if p[:name] == 'FLUTTER_FRAMEWORK_DIR'
48 | symlink = File.join('.symlinks', 'flutter')
49 | File.symlink(File.dirname(p[:path]), symlink)
50 | pod 'Flutter', :path => File.join(symlink, File.basename(p[:path]))
51 | end
52 | }
53 |
54 | # Plugin Pods
55 | plugin_pods = parse_KV_file('../.flutter-plugins')
56 | plugin_pods.map { |p|
57 | symlink = File.join('.symlinks', 'plugins', p[:name])
58 | File.symlink(p[:path], symlink)
59 | pod p[:name], :path => File.join(symlink, 'ios')
60 | }
61 | end
62 |
63 | post_install do |installer|
64 | installer.pods_project.targets.each do |target|
65 | target.build_configurations.each do |config|
66 | config.build_settings['ENABLE_BITCODE'] = 'NO'
67 | end
68 | end
69 | end
70 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | BuildSystemType
6 | Original
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
54 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
75 |
81 |
82 |
83 |
84 |
86 |
87 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | BuildSystemType
6 | Original
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner/AppDelegate.h:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 |
4 | @interface AppDelegate : FlutterAppDelegate
5 |
6 | @end
7 |
--------------------------------------------------------------------------------
/ios/Runner/AppDelegate.m:
--------------------------------------------------------------------------------
1 | #include "AppDelegate.h"
2 | #include "GeneratedPluginRegistrant.h"
3 |
4 | @implementation AppDelegate
5 |
6 | - (BOOL)application:(UIApplication *)application
7 | didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
8 | [GeneratedPluginRegistrant registerWithRegistry:self];
9 | // Override point for customization after application launch.
10 | return [super application:application didFinishLaunchingWithOptions:launchOptions];
11 | }
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "20x20",
5 | "idiom" : "iphone",
6 | "filename" : "Icon-App-20x20@2x.png",
7 | "scale" : "2x"
8 | },
9 | {
10 | "size" : "20x20",
11 | "idiom" : "iphone",
12 | "filename" : "Icon-App-20x20@3x.png",
13 | "scale" : "3x"
14 | },
15 | {
16 | "size" : "29x29",
17 | "idiom" : "iphone",
18 | "filename" : "Icon-App-29x29@1x.png",
19 | "scale" : "1x"
20 | },
21 | {
22 | "size" : "29x29",
23 | "idiom" : "iphone",
24 | "filename" : "Icon-App-29x29@2x.png",
25 | "scale" : "2x"
26 | },
27 | {
28 | "size" : "29x29",
29 | "idiom" : "iphone",
30 | "filename" : "Icon-App-29x29@3x.png",
31 | "scale" : "3x"
32 | },
33 | {
34 | "size" : "40x40",
35 | "idiom" : "iphone",
36 | "filename" : "Icon-App-40x40@2x.png",
37 | "scale" : "2x"
38 | },
39 | {
40 | "size" : "40x40",
41 | "idiom" : "iphone",
42 | "filename" : "Icon-App-40x40@3x.png",
43 | "scale" : "3x"
44 | },
45 | {
46 | "size" : "60x60",
47 | "idiom" : "iphone",
48 | "filename" : "Icon-App-60x60@2x.png",
49 | "scale" : "2x"
50 | },
51 | {
52 | "size" : "60x60",
53 | "idiom" : "iphone",
54 | "filename" : "Icon-App-60x60@3x.png",
55 | "scale" : "3x"
56 | },
57 | {
58 | "size" : "20x20",
59 | "idiom" : "ipad",
60 | "filename" : "Icon-App-20x20@1x.png",
61 | "scale" : "1x"
62 | },
63 | {
64 | "size" : "20x20",
65 | "idiom" : "ipad",
66 | "filename" : "Icon-App-20x20@2x.png",
67 | "scale" : "2x"
68 | },
69 | {
70 | "size" : "29x29",
71 | "idiom" : "ipad",
72 | "filename" : "Icon-App-29x29@1x.png",
73 | "scale" : "1x"
74 | },
75 | {
76 | "size" : "29x29",
77 | "idiom" : "ipad",
78 | "filename" : "Icon-App-29x29@2x.png",
79 | "scale" : "2x"
80 | },
81 | {
82 | "size" : "40x40",
83 | "idiom" : "ipad",
84 | "filename" : "Icon-App-40x40@1x.png",
85 | "scale" : "1x"
86 | },
87 | {
88 | "size" : "40x40",
89 | "idiom" : "ipad",
90 | "filename" : "Icon-App-40x40@2x.png",
91 | "scale" : "2x"
92 | },
93 | {
94 | "size" : "76x76",
95 | "idiom" : "ipad",
96 | "filename" : "Icon-App-76x76@1x.png",
97 | "scale" : "1x"
98 | },
99 | {
100 | "size" : "76x76",
101 | "idiom" : "ipad",
102 | "filename" : "Icon-App-76x76@2x.png",
103 | "scale" : "2x"
104 | },
105 | {
106 | "size" : "83.5x83.5",
107 | "idiom" : "ipad",
108 | "filename" : "Icon-App-83.5x83.5@2x.png",
109 | "scale" : "2x"
110 | },
111 | {
112 | "size" : "1024x1024",
113 | "idiom" : "ios-marketing",
114 | "filename" : "Icon-App-1024x1024@1x.png",
115 | "scale" : "1x"
116 | }
117 | ],
118 | "info" : {
119 | "version" : 1,
120 | "author" : "xcode"
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AYM1607/do_more/c415a2d1396e45facd11e6b60f2821424df99216/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AYM1607/do_more/c415a2d1396e45facd11e6b60f2821424df99216/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/AYM1607/do_more/c415a2d1396e45facd11e6b60f2821424df99216/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/AYM1607/do_more/c415a2d1396e45facd11e6b60f2821424df99216/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/AYM1607/do_more/c415a2d1396e45facd11e6b60f2821424df99216/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/AYM1607/do_more/c415a2d1396e45facd11e6b60f2821424df99216/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/AYM1607/do_more/c415a2d1396e45facd11e6b60f2821424df99216/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/AYM1607/do_more/c415a2d1396e45facd11e6b60f2821424df99216/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/AYM1607/do_more/c415a2d1396e45facd11e6b60f2821424df99216/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/AYM1607/do_more/c415a2d1396e45facd11e6b60f2821424df99216/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/AYM1607/do_more/c415a2d1396e45facd11e6b60f2821424df99216/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/AYM1607/do_more/c415a2d1396e45facd11e6b60f2821424df99216/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/AYM1607/do_more/c415a2d1396e45facd11e6b60f2821424df99216/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/AYM1607/do_more/c415a2d1396e45facd11e6b60f2821424df99216/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AYM1607/do_more/c415a2d1396e45facd11e6b60f2821424df99216/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AYM1607/do_more/c415a2d1396e45facd11e6b60f2821424df99216/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AYM1607/do_more/c415a2d1396e45facd11e6b60f2821424df99216/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AYM1607/do_more/c415a2d1396e45facd11e6b60f2821424df99216/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
--------------------------------------------------------------------------------
/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.
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/ios/Runner/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | do_more
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | $(FLUTTER_BUILD_NAME)
19 | CFBundleSignature
20 | ????
21 | CFBundleURLTypes
22 |
23 |
24 | CFBundleTypeRole
25 | Editor
26 | CFBundleURLSchemes
27 |
28 | com.googleusercontent.apps.854370768062-bsmn2u8jngin4g6ior8crnir42t8p9u4
29 |
30 |
31 |
32 | CFBundleVersion
33 | $(FLUTTER_BUILD_NUMBER)
34 | LSRequiresIPhoneOS
35 |
36 | NSCameraUsageDescription
37 | Allow Do more to take pictures to add it to your gallery
38 | NSMicrophoneUsageDescription
39 | Allow Do more to take videos and add them to your gallery
40 | NSPhotoLibraryUsageDescription
41 | Allow Do more to upload photos that already took
42 | UILaunchStoryboardName
43 | LaunchScreen
44 | UIMainStoryboardFile
45 | Main
46 | UISupportedInterfaceOrientations
47 |
48 | UIInterfaceOrientationPortrait
49 | UIInterfaceOrientationLandscapeLeft
50 | UIInterfaceOrientationLandscapeRight
51 |
52 | UISupportedInterfaceOrientations~ipad
53 |
54 | UIInterfaceOrientationPortrait
55 | UIInterfaceOrientationPortraitUpsideDown
56 | UIInterfaceOrientationLandscapeLeft
57 | UIInterfaceOrientationLandscapeRight
58 |
59 | UIViewControllerBasedStatusBarAppearance
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/ios/Runner/main.m:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 | #import "AppDelegate.h"
4 |
5 | int main(int argc, char* argv[]) {
6 | @autoreleasepool {
7 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/lib/main.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter/services.dart';
3 |
4 | import 'src/App.dart';
5 |
6 | main() async {
7 | SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.light);
8 | await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
9 | runApp(App());
10 | }
11 |
--------------------------------------------------------------------------------
/lib/src/App.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | import 'screens/archive_screen.dart';
4 | import 'screens/event_screen.dart';
5 | import 'screens/events_screen.dart';
6 | import 'screens/home_screen.dart';
7 | import 'screens/initial_loading_screen.dart';
8 | import 'screens/login_screen.dart';
9 | import 'screens/new_event_screen.dart';
10 | import 'screens/new_image_screen.dart';
11 | import 'screens/task_screen.dart';
12 |
13 | class App extends StatelessWidget {
14 | Widget build(BuildContext context) {
15 | return MaterialApp(
16 | title: 'Do more',
17 | //home: Text('Start'),
18 | onGenerateRoute: routes,
19 | theme: ThemeData(
20 | // Accent color is set to be used by the floating action button.
21 | accentColor: Color(0xFF707070),
22 | iconTheme: IconThemeData(
23 | color: Colors.white,
24 | ),
25 | canvasColor: Color.fromRGBO(23, 25, 29, 1.0),
26 | cardColor: Color.fromRGBO(36, 39, 44, 1.0),
27 | cursorColor: Color.fromRGBO(112, 112, 112, 1),
28 | fontFamily: 'IBM Plex Sans',
29 | ),
30 | );
31 | }
32 |
33 | Route routes(RouteSettings settings) {
34 | final List routeTokens = settings.name.split('/');
35 | print(routeTokens);
36 | if (routeTokens.first == 'login') {
37 | return MaterialPageRoute(
38 | builder: (BuildContext context) {
39 | return LoginScreen();
40 | },
41 | );
42 | } else if (routeTokens.first == 'home') {
43 | return MaterialPageRoute(
44 | builder: (BuildContext context) {
45 | return HomeScreen();
46 | },
47 | );
48 | } else if (routeTokens.first == 'newTask') {
49 | return MaterialPageRoute(
50 | builder: (BuildContext context) {
51 | return TaskScreen();
52 | },
53 | );
54 | } else if (routeTokens.first == 'editTask') {
55 | return MaterialPageRoute(
56 | builder: (BuildContext context) {
57 | return TaskScreen(
58 | isEdit: true,
59 | taskId: routeTokens[1],
60 | );
61 | },
62 | );
63 | } else if (routeTokens.first == 'newImage') {
64 | String eventName;
65 | if (routeTokens.length > 1) {
66 | eventName = routeTokens[1];
67 | }
68 | return MaterialPageRoute(
69 | builder: (BuildContext context) {
70 | return NewImageScreen(
71 | defaultEventName: eventName,
72 | );
73 | },
74 | );
75 | } else if (routeTokens.first == 'event') {
76 | return MaterialPageRoute(
77 | builder: (BuildContext context) {
78 | return EventScreen(
79 | eventName: routeTokens[1],
80 | );
81 | },
82 | );
83 | } else if (routeTokens.first == 'events') {
84 | return MaterialPageRoute(
85 | builder: (BuildContext context) {
86 | return EventsScreen();
87 | },
88 | );
89 | } else if (routeTokens.first == 'newEvent') {
90 | return MaterialPageRoute(
91 | builder: (BuildContext contex) {
92 | return NewEventScreen();
93 | },
94 | );
95 | } else if (routeTokens.first == 'archive') {
96 | return MaterialPageRoute(
97 | builder: (BuildContext context) {
98 | return ArchiveScreen();
99 | },
100 | );
101 | }
102 | // Default route.
103 | return MaterialPageRoute(
104 | builder: (BuildContext context) {
105 | return InitialLoadingScreen();
106 | },
107 | );
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/lib/src/blocs/archive_bloc.dart:
--------------------------------------------------------------------------------
1 | import 'package:rxdart/rxdart.dart';
2 |
3 | import '../utils.dart' show kTaskListPriorityTransforemer;
4 | import '../models/task_model.dart';
5 | import '../resources/firestore_provider.dart';
6 | import '../resources/google_sign_in_provider.dart';
7 | import '../services/auth_service.dart';
8 |
9 | export '../services/auth_service.dart' show FirebaseUser;
10 |
11 | class ArchiveBloc {
12 | /// An instance of the auth service.
13 | AuthService _auth = authService;
14 |
15 | /// An instance of the firestore provider.
16 | FirestoreProvider _firestore = firestoreProvider;
17 |
18 | final _tasks = BehaviorSubject>();
19 |
20 | // Stream getters.
21 | /// An observable of the current logged in user.
22 | Observable get userStream => _auth.userStream;
23 |
24 | /// An observable of the done tasks linked to the current user.
25 | Observable> get tasks =>
26 | _tasks.stream.transform(kTaskListPriorityTransforemer);
27 |
28 | void fetchTasks() async {
29 | final userModel = await _auth.getCurrentUserModel();
30 | _firestore.getUserTasks(userModel.username, done: true).pipe(_tasks);
31 | }
32 |
33 | void undoTask(TaskModel task) {
34 | _firestore.updateTask(task.id, done: false);
35 | }
36 |
37 | dispose() async {
38 | await _tasks.drain();
39 | _tasks.close();
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/lib/src/blocs/event_bloc.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 | import 'dart:io';
3 |
4 | import 'package:meta/meta.dart';
5 | import 'package:rxdart/rxdart.dart';
6 |
7 | import '../mixins/upload_status_mixin.dart';
8 | import '../models/event_model.dart';
9 | import '../models/task_model.dart';
10 | import '../models/user_model.dart';
11 | import '../resources/firestore_provider.dart';
12 | import '../resources/firebase_storage_provider.dart';
13 | import '../services/auth_service.dart';
14 | import '../utils.dart'
15 | show kTaskListPriorityTransforemer, getImageThumbnailPath;
16 |
17 | /// A business logic component that manages the state for an event screen.
18 | class EventBloc extends Object with UploadStatusMixin {
19 | /// The name of the event being shown.
20 | final String eventName;
21 |
22 | /// An instance of a firestore provider.
23 | final FirestoreProvider _firestore = firestoreProvider;
24 |
25 | /// An instance of the firebase sotrage provider.
26 | final FirebaseStorageProvider _storage = storageProvider;
27 |
28 | /// An instace of the auth service.
29 | final AuthService _auth = authService;
30 |
31 | /// A subject of list of task model.
32 | final _tasks = BehaviorSubject>();
33 |
34 | /// A subject of the list of image paths for this event.
35 | final _imagesPaths = BehaviorSubject>();
36 |
37 | /// A subject of String paths.
38 | final _imagesFetcher = PublishSubject();
39 |
40 | /// A subject of String paths.
41 | final _imagesThumbnailsFetcher = PublishSubject();
42 |
43 | /// A subject of a cache that contains the image files.
44 | final _thumbnails = BehaviorSubject