├── server ├── bin │ ├── src │ │ └── main │ │ │ └── resources │ │ │ └── application.properties │ ├── .mvn │ │ └── wrapper │ │ │ ├── maven-wrapper.jar │ │ │ └── maven-wrapper.properties │ ├── .gitignore │ ├── pom.xml │ ├── mvnw.cmd │ └── mvnw ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties ├── .gitignore ├── src │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── rowan │ │ │ │ └── ruber │ │ │ │ ├── Utils.java │ │ │ │ ├── RuberApplication.java │ │ │ │ ├── model │ │ │ │ ├── SortByDay.java │ │ │ │ ├── google_maps │ │ │ │ │ ├── Location.java │ │ │ │ │ ├── Northeast.java │ │ │ │ │ ├── Southwest.java │ │ │ │ │ ├── Viewport.java │ │ │ │ │ ├── Bounds.java │ │ │ │ │ ├── GeoencodingResult.java │ │ │ │ │ ├── AddressComponent.java │ │ │ │ │ ├── Geometry.java │ │ │ │ │ └── Result.java │ │ │ │ ├── Day.java │ │ │ │ ├── Message.java │ │ │ │ ├── Chatroom.java │ │ │ │ ├── Address.java │ │ │ │ ├── Profile.java │ │ │ │ └── Schedule.java │ │ │ │ ├── repository │ │ │ │ ├── AddressRepository.java │ │ │ │ ├── MessageRepository.java │ │ │ │ ├── ChatroomRepository.java │ │ │ │ ├── ScheduleRepository.java │ │ │ │ └── ProfileRepository.java │ │ │ │ ├── io │ │ │ │ └── HelloController.java │ │ │ │ ├── MapsManager.java │ │ │ │ ├── Authenticator.java │ │ │ │ ├── Ids.java │ │ │ │ └── Search.java │ │ └── resources │ │ │ └── application.properties │ └── test │ │ └── java │ │ └── com │ │ └── rowan │ │ └── ruber │ │ └── RuberApplicationTests.java ├── pom.xml ├── mvnw.cmd └── mvnw ├── ruber ├── android │ ├── gradle.properties │ ├── app │ │ ├── src │ │ │ └── main │ │ │ │ ├── web_hi_res_512.png │ │ │ │ ├── res │ │ │ │ ├── mipmap-hdpi │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ └── rowanuniversity.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ └── rowanuniversity.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ └── rowanuniversity.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ └── rowanuniversity.png │ │ │ │ ├── values │ │ │ │ │ └── styles.xml │ │ │ │ └── drawable │ │ │ │ │ └── launch_background.xml │ │ │ │ ├── gen │ │ │ │ └── com │ │ │ │ │ └── ruber │ │ │ │ │ └── ruber │ │ │ │ │ ├── R.java │ │ │ │ │ ├── Manifest.java │ │ │ │ │ └── BuildConfig.java │ │ │ │ ├── kotlin │ │ │ │ └── com │ │ │ │ │ └── ruber │ │ │ │ │ └── ruber │ │ │ │ │ └── MainActivity.kt │ │ │ │ └── AndroidManifest.xml │ │ ├── google-services.json │ │ └── build.gradle │ ├── .gitignore │ ├── gradle │ │ └── wrapper │ │ │ └── gradle-wrapper.properties │ ├── settings.gradle │ └── build.gradle ├── 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 │ │ ├── Base.lproj │ │ │ ├── Main.storyboard │ │ │ └── LaunchScreen.storyboard │ │ └── Info.plist │ ├── Runner.xcworkspace │ │ └── contents.xcworkspacedata │ ├── Runner.xcodeproj │ │ ├── project.xcworkspace │ │ │ └── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ └── .gitignore ├── assets │ ├── RowanCampus.jpg │ ├── fonts │ │ ├── Bungee-Regular.ttf │ │ ├── Heebo-Regular.ttf │ │ ├── Roboto-Regular.ttf │ │ ├── Audiowide-Regular.ttf │ │ ├── BungeeShade-Regular.ttf │ │ └── BungeeInline-Regular.ttf │ └── User_Structure.json ├── .gitignore ├── images │ └── rowanuniversity.png ├── README.md ├── .metadata ├── lib │ ├── Constants.dart │ ├── UserModel.dart │ ├── AddressPostModel.dart │ ├── MessageModel.dart │ ├── GoingToRowan.dart │ ├── ScheduleModel.dart │ ├── AddressModel.dart │ ├── RideScreen.dart │ ├── AppDrawer.dart │ ├── ProfileModel.dart │ ├── ChatroomModel.dart │ ├── Main.dart │ ├── matches_screen.dart │ ├── AuthScreen.dart │ ├── initialaddaddress.dart │ └── ChatRoomScreen.dart └── pubspec.yaml ├── Ryde.mp4 ├── Design Document.pdf ├── Ryde User Manual.pdf ├── Fall 2018 Senior Project Final Presentation - Ryde.pdf ├── ISSUES.txt ├── README.md └── .gitignore /server/bin/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ruber/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | -------------------------------------------------------------------------------- /ruber/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /ruber/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /ruber/ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" -------------------------------------------------------------------------------- /Ryde.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TylerCarberry/RowanRideshare/HEAD/Ryde.mp4 -------------------------------------------------------------------------------- /Design Document.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TylerCarberry/RowanRideshare/HEAD/Design Document.pdf -------------------------------------------------------------------------------- /Ryde User Manual.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TylerCarberry/RowanRideshare/HEAD/Ryde User Manual.pdf -------------------------------------------------------------------------------- /ruber/assets/RowanCampus.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TylerCarberry/RowanRideshare/HEAD/ruber/assets/RowanCampus.jpg -------------------------------------------------------------------------------- /ruber/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .dart_tool/ 3 | 4 | .packages 5 | .pub/ 6 | 7 | build/ 8 | 9 | .flutter-plugins 10 | -------------------------------------------------------------------------------- /ruber/images/rowanuniversity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TylerCarberry/RowanRideshare/HEAD/ruber/images/rowanuniversity.png -------------------------------------------------------------------------------- /ruber/assets/fonts/Bungee-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TylerCarberry/RowanRideshare/HEAD/ruber/assets/fonts/Bungee-Regular.ttf -------------------------------------------------------------------------------- /ruber/assets/fonts/Heebo-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TylerCarberry/RowanRideshare/HEAD/ruber/assets/fonts/Heebo-Regular.ttf -------------------------------------------------------------------------------- /ruber/assets/fonts/Roboto-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TylerCarberry/RowanRideshare/HEAD/ruber/assets/fonts/Roboto-Regular.ttf -------------------------------------------------------------------------------- /server/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TylerCarberry/RowanRideshare/HEAD/server/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /ruber/assets/fonts/Audiowide-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TylerCarberry/RowanRideshare/HEAD/ruber/assets/fonts/Audiowide-Regular.ttf -------------------------------------------------------------------------------- /ruber/assets/fonts/BungeeShade-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TylerCarberry/RowanRideshare/HEAD/ruber/assets/fonts/BungeeShade-Regular.ttf -------------------------------------------------------------------------------- /server/bin/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TylerCarberry/RowanRideshare/HEAD/server/bin/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /ruber/assets/fonts/BungeeInline-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TylerCarberry/RowanRideshare/HEAD/ruber/assets/fonts/BungeeInline-Regular.ttf -------------------------------------------------------------------------------- /ruber/android/app/src/main/web_hi_res_512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TylerCarberry/RowanRideshare/HEAD/ruber/android/app/src/main/web_hi_res_512.png -------------------------------------------------------------------------------- /server/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.4/apache-maven-3.5.4-bin.zip 2 | -------------------------------------------------------------------------------- /server/bin/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.4/apache-maven-3.5.4-bin.zip 2 | -------------------------------------------------------------------------------- /Fall 2018 Senior Project Final Presentation - Ryde.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TylerCarberry/RowanRideshare/HEAD/Fall 2018 Senior Project Final Presentation - Ryde.pdf -------------------------------------------------------------------------------- /ruber/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TylerCarberry/RowanRideshare/HEAD/ruber/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /ruber/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TylerCarberry/RowanRideshare/HEAD/ruber/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /ruber/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TylerCarberry/RowanRideshare/HEAD/ruber/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /ruber/README.md: -------------------------------------------------------------------------------- 1 | # ruber 2 | 3 | Rowan Carpool 4 | 5 | ## Getting Started 6 | 7 | For help getting started with Flutter, view our online 8 | [documentation](https://flutter.io/). 9 | -------------------------------------------------------------------------------- /ruber/android/app/src/main/res/mipmap-hdpi/rowanuniversity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TylerCarberry/RowanRideshare/HEAD/ruber/android/app/src/main/res/mipmap-hdpi/rowanuniversity.png -------------------------------------------------------------------------------- /ruber/android/app/src/main/res/mipmap-mdpi/rowanuniversity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TylerCarberry/RowanRideshare/HEAD/ruber/android/app/src/main/res/mipmap-mdpi/rowanuniversity.png -------------------------------------------------------------------------------- /ruber/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TylerCarberry/RowanRideshare/HEAD/ruber/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /ruber/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TylerCarberry/RowanRideshare/HEAD/ruber/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /ruber/android/app/src/main/res/mipmap-xxhdpi/rowanuniversity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TylerCarberry/RowanRideshare/HEAD/ruber/android/app/src/main/res/mipmap-xxhdpi/rowanuniversity.png -------------------------------------------------------------------------------- /ruber/android/app/src/main/res/mipmap-xxxhdpi/rowanuniversity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TylerCarberry/RowanRideshare/HEAD/ruber/android/app/src/main/res/mipmap-xxxhdpi/rowanuniversity.png -------------------------------------------------------------------------------- /ruber/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TylerCarberry/RowanRideshare/HEAD/ruber/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /ruber/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TylerCarberry/RowanRideshare/HEAD/ruber/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /ruber/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TylerCarberry/RowanRideshare/HEAD/ruber/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /ruber/android/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | *.class 3 | .gradle 4 | /local.properties 5 | /.idea/workspace.xml 6 | /.idea/libraries 7 | .DS_Store 8 | /build 9 | /captures 10 | GeneratedPluginRegistrant.java 11 | -------------------------------------------------------------------------------- /ruber/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TylerCarberry/RowanRideshare/HEAD/ruber/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /ruber/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TylerCarberry/RowanRideshare/HEAD/ruber/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /ruber/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TylerCarberry/RowanRideshare/HEAD/ruber/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /ruber/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TylerCarberry/RowanRideshare/HEAD/ruber/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /ruber/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TylerCarberry/RowanRideshare/HEAD/ruber/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /ruber/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TylerCarberry/RowanRideshare/HEAD/ruber/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /ruber/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TylerCarberry/RowanRideshare/HEAD/ruber/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /ruber/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TylerCarberry/RowanRideshare/HEAD/ruber/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /ruber/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TylerCarberry/RowanRideshare/HEAD/ruber/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /ruber/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TylerCarberry/RowanRideshare/HEAD/ruber/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /ruber/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TylerCarberry/RowanRideshare/HEAD/ruber/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /ruber/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TylerCarberry/RowanRideshare/HEAD/ruber/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /ruber/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TylerCarberry/RowanRideshare/HEAD/ruber/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /ruber/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TylerCarberry/RowanRideshare/HEAD/ruber/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /ruber/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TylerCarberry/RowanRideshare/HEAD/ruber/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /ruber/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ruber/android/app/src/main/gen/com/ruber/ruber/R.java: -------------------------------------------------------------------------------- 1 | /*___Generated_by_IDEA___*/ 2 | 3 | package com.ruber.ruber; 4 | 5 | /* This stub is only used by the IDE. It is NOT the R class actually packed into the APK */ 6 | public final class R { 7 | } -------------------------------------------------------------------------------- /ruber/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ruber/android/app/src/main/gen/com/ruber/ruber/Manifest.java: -------------------------------------------------------------------------------- 1 | /*___Generated_by_IDEA___*/ 2 | 3 | package com.ruber.ruber; 4 | 5 | /* This stub is only used by the IDE. It is NOT the Manifest class actually packed into the APK */ 6 | public final class Manifest { 7 | } -------------------------------------------------------------------------------- /ruber/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.4-all.zip 7 | -------------------------------------------------------------------------------- /ruber/.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: 5ab9e70727d858def3a586db7fb98ee580352957 8 | channel: beta 9 | -------------------------------------------------------------------------------- /ISSUES.txt: -------------------------------------------------------------------------------- 1 | Here are a list of existing bugs/issues: 2 | 3 | 1.The Schedule button on the home screen does not show the current schedule. 4 | -Ideally we show the schedule itself much like we show the address in Edit Address (with hint text). 5 | -Or we can show the schedule in another format with a brand new widget (not recommended). 6 | -------------------------------------------------------------------------------- /ruber/android/app/src/main/gen/com/ruber/ruber/BuildConfig.java: -------------------------------------------------------------------------------- 1 | /*___Generated_by_IDEA___*/ 2 | 3 | package com.ruber.ruber; 4 | 5 | /* This stub is only used by the IDE. It is NOT the BuildConfig class actually packed into the APK */ 6 | public final class BuildConfig { 7 | public final static boolean DEBUG = Boolean.parseBoolean(null); 8 | } -------------------------------------------------------------------------------- /ruber/assets/User_Structure.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 1, 3 | "name": "Firstname Lastname", 4 | "email": "firstnamel0@students.rowan.edu", 5 | "address": { 6 | "id": 1, 7 | "streetAddress": "201 Mullica Hill Road", 8 | "city": "Glassboro", 9 | "zipCode": "08028", 10 | "state": "NJ", 11 | "latitude": 39.70779, 12 | "longitude": -75.11383 13 | }, 14 | "createdDate": "2018-10-28", 15 | "schedules": [] 16 | } -------------------------------------------------------------------------------- /server/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | .sts4-cache 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | /nbproject/private/ 21 | /build/ 22 | /nbbuild/ 23 | /dist/ 24 | /nbdist/ 25 | /.nb-gradle/ -------------------------------------------------------------------------------- /server/bin/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | .sts4-cache 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | /nbproject/private/ 21 | /build/ 22 | /nbbuild/ 23 | /dist/ 24 | /nbdist/ 25 | /.nb-gradle/ -------------------------------------------------------------------------------- /ruber/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. -------------------------------------------------------------------------------- /server/src/main/java/com/rowan/ruber/Utils.java: -------------------------------------------------------------------------------- 1 | package com.rowan.ruber; 2 | 3 | import java.io.ByteArrayInputStream; 4 | import java.io.InputStream; 5 | import java.nio.charset.Charset; 6 | 7 | public class Utils { 8 | 9 | public static InputStream convertStringToStream(String str) { 10 | return new ByteArrayInputStream(str.getBytes(Charset.defaultCharset())); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /server/src/main/java/com/rowan/ruber/RuberApplication.java: -------------------------------------------------------------------------------- 1 | package com.rowan.ruber; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class RuberApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(RuberApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /ruber/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /server/src/main/java/com/rowan/ruber/model/SortByDay.java: -------------------------------------------------------------------------------- 1 | package com.rowan.ruber.model; 2 | 3 | import java.util.Comparator; 4 | 5 | public class SortByDay implements Comparator { 6 | // Used for sorting in ascending order of 7 | // roll number 8 | public int compare(Schedule a, Schedule b) 9 | { 10 | return a.getDay().compareTo(b.getDay()); 11 | } 12 | } 13 | 14 | -------------------------------------------------------------------------------- /server/src/main/java/com/rowan/ruber/repository/AddressRepository.java: -------------------------------------------------------------------------------- 1 | package com.rowan.ruber.repository; 2 | 3 | import org.springframework.data.repository.CrudRepository; 4 | 5 | import com.rowan.ruber.model.Address; 6 | 7 | // This will be AUTO IMPLEMENTED by Spring into a Bean called addressRepository 8 | // CRUD refers Create, Read, Update, Delete 9 | public interface AddressRepository extends CrudRepository { 10 | } -------------------------------------------------------------------------------- /ruber/android/app/src/main/kotlin/com/ruber/ruber/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.ruber.ruber 2 | 3 | import android.os.Bundle 4 | 5 | import io.flutter.app.FlutterActivity 6 | import io.flutter.plugins.GeneratedPluginRegistrant 7 | 8 | class MainActivity(): FlutterActivity() { 9 | override fun onCreate(savedInstanceState: Bundle?) { 10 | super.onCreate(savedInstanceState) 11 | GeneratedPluginRegistrant.registerWith(this) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /server/src/main/java/com/rowan/ruber/repository/MessageRepository.java: -------------------------------------------------------------------------------- 1 | package com.rowan.ruber.repository; 2 | 3 | import org.springframework.data.repository.CrudRepository; 4 | import com.rowan.ruber.model.Message; 5 | 6 | // This will be AUTO IMPLEMENTED by Spring into a Bean called messageRepository in the RuberController 7 | // CRUD refers Create, Read, Update, Delete 8 | public interface MessageRepository extends CrudRepository { 9 | 10 | } -------------------------------------------------------------------------------- /server/src/test/java/com/rowan/ruber/RuberApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.rowan.ruber; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class RuberApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /server/src/main/java/com/rowan/ruber/repository/ChatroomRepository.java: -------------------------------------------------------------------------------- 1 | package com.rowan.ruber.repository; 2 | 3 | import org.springframework.data.repository.CrudRepository; 4 | import com.rowan.ruber.model.Chatroom; 5 | 6 | // This will be AUTO IMPLEMENTED by Spring into a Bean called chatroomRepository in the RuberController 7 | // CRUD refers Create, Read, Update, Delete 8 | public interface ChatroomRepository extends CrudRepository { 9 | 10 | } -------------------------------------------------------------------------------- /server/src/main/java/com/rowan/ruber/repository/ScheduleRepository.java: -------------------------------------------------------------------------------- 1 | package com.rowan.ruber.repository; 2 | 3 | import org.springframework.data.repository.CrudRepository; 4 | import com.rowan.ruber.model.Schedule; 5 | 6 | // This will be AUTO IMPLEMENTED by Spring into a Bean called scheduleRepository in the RuberController 7 | // CRUD refers Create, Read, Update, Delete 8 | public interface ScheduleRepository extends CrudRepository { 9 | 10 | } -------------------------------------------------------------------------------- /ruber/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: [UIApplicationLaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /server/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.jpa.hibernate.ddl-auto=none 2 | spring.datasource.url=jdbc:mysql://ec2-34-230-33-210.compute-1.amazonaws.com:3306/rideshare 3 | spring.datasource.username=user 4 | spring.datasource.password=Rideshare@2018 5 | spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl 6 | spring.jackson.serialization.indent_output=true 7 | spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect -------------------------------------------------------------------------------- /server/src/main/java/com/rowan/ruber/io/HelloController.java: -------------------------------------------------------------------------------- 1 | package com.rowan.ruber.io; 2 | 3 | import org.springframework.web.bind.annotation.*; 4 | 5 | /** 6 | * A test controller to make sure the server is running 7 | */ 8 | @RequestMapping("/hello") 9 | @RestController 10 | public class HelloController { 11 | 12 | @GetMapping("/greeting") 13 | public String index(@RequestParam(name="name", required=false, defaultValue="World") String name) { 14 | return "Hello, " + name + "!"; 15 | } 16 | } -------------------------------------------------------------------------------- /ruber/lib/Constants.dart: -------------------------------------------------------------------------------- 1 | /// Constants.dart 2 | /// 3 | /// Purpose: 4 | /// This file is used to define the URL for the back end server -- AWS's URL 5 | /// Additional URLs are provided for testing and ngrok 6 | 7 | 8 | // If you want to use your AWS instead of your local server, uncomment this line 9 | final String BASE_URL = "http://ec2-34-230-33-210.compute-1.amazonaws.com:8080"; 10 | 11 | //final String BASE_URL = "http://10.0.2.2:8080"; 12 | 13 | //if you need ngrok 14 | //final String BASE_URL = "http://61b5267a.ngrok.io"; 15 | -------------------------------------------------------------------------------- /ruber/android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /server/src/main/java/com/rowan/ruber/model/google_maps/Location.java: -------------------------------------------------------------------------------- 1 | 2 | package com.rowan.ruber.model.google_maps; 3 | 4 | public class Location { 5 | 6 | private Double lat; 7 | private Double lng; 8 | 9 | public Double getLat() { 10 | return lat; 11 | } 12 | 13 | public void setLat(Double lat) { 14 | this.lat = lat; 15 | } 16 | 17 | public Double getLng() { 18 | return lng; 19 | } 20 | 21 | public void setLng(Double lng) { 22 | this.lng = lng; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /server/src/main/java/com/rowan/ruber/model/google_maps/Northeast.java: -------------------------------------------------------------------------------- 1 | 2 | package com.rowan.ruber.model.google_maps; 3 | 4 | public class Northeast { 5 | 6 | private Double lat; 7 | private Double lng; 8 | 9 | public Double getLat() { 10 | return lat; 11 | } 12 | 13 | public void setLat(Double lat) { 14 | this.lat = lat; 15 | } 16 | 17 | public Double getLng() { 18 | return lng; 19 | } 20 | 21 | public void setLng(Double lng) { 22 | this.lng = lng; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /server/src/main/java/com/rowan/ruber/model/google_maps/Southwest.java: -------------------------------------------------------------------------------- 1 | 2 | package com.rowan.ruber.model.google_maps; 3 | 4 | public class Southwest { 5 | 6 | private Double lat; 7 | private Double lng; 8 | 9 | public Double getLat() { 10 | return lat; 11 | } 12 | 13 | public void setLat(Double lat) { 14 | this.lat = lat; 15 | } 16 | 17 | public Double getLng() { 18 | return lng; 19 | } 20 | 21 | public void setLng(Double lng) { 22 | this.lng = lng; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /ruber/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 | -------------------------------------------------------------------------------- /ruber/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 | -------------------------------------------------------------------------------- /server/src/main/java/com/rowan/ruber/model/google_maps/Viewport.java: -------------------------------------------------------------------------------- 1 | 2 | package com.rowan.ruber.model.google_maps; 3 | 4 | public class Viewport { 5 | 6 | private Northeast northeast; 7 | private Southwest southwest; 8 | 9 | public Northeast getNortheast() { 10 | return northeast; 11 | } 12 | 13 | public void setNortheast(Northeast northeast) { 14 | this.northeast = northeast; 15 | } 16 | 17 | public Southwest getSouthwest() { 18 | return southwest; 19 | } 20 | 21 | public void setSouthwest(Southwest southwest) { 22 | this.southwest = southwest; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /server/src/main/java/com/rowan/ruber/repository/ProfileRepository.java: -------------------------------------------------------------------------------- 1 | package com.rowan.ruber.repository; 2 | 3 | import org.jboss.logging.Param; 4 | import org.springframework.data.jpa.repository.Query; 5 | import org.springframework.data.repository.CrudRepository; 6 | 7 | import java.util.Optional; 8 | 9 | import com.rowan.ruber.model.Profile; 10 | 11 | // This will be AUTO IMPLEMENTED by Spring into a Bean called profileRepository in the RuberController 12 | // CRUD refers Create, Read, Update, Delete 13 | public interface ProfileRepository extends CrudRepository { 14 | 15 | public Optional findByEmailAddress(String emailAddress); 16 | } -------------------------------------------------------------------------------- /server/src/main/java/com/rowan/ruber/model/google_maps/Bounds.java: -------------------------------------------------------------------------------- 1 | 2 | package com.rowan.ruber.model.google_maps; 3 | 4 | public class Bounds { 5 | 6 | private Northeast northeast; 7 | private Southwest southwest; 8 | 9 | public Bounds() { 10 | } 11 | 12 | public Northeast getNortheast() { 13 | return northeast; 14 | } 15 | 16 | public void setNortheast(Northeast northeast) { 17 | this.northeast = northeast; 18 | } 19 | 20 | public Southwest getSouthwest() { 21 | return southwest; 22 | } 23 | 24 | public void setSouthwest(Southwest southwest) { 25 | this.southwest = southwest; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /ruber/ios/.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .vagrant/ 3 | .sconsign.dblite 4 | .svn/ 5 | 6 | .DS_Store 7 | *.swp 8 | profile 9 | 10 | DerivedData/ 11 | build/ 12 | GeneratedPluginRegistrant.h 13 | GeneratedPluginRegistrant.m 14 | 15 | .generated/ 16 | 17 | *.pbxuser 18 | *.mode1v3 19 | *.mode2v3 20 | *.perspectivev3 21 | 22 | !default.pbxuser 23 | !default.mode1v3 24 | !default.mode2v3 25 | !default.perspectivev3 26 | 27 | xcuserdata 28 | 29 | *.moved-aside 30 | 31 | *.pyc 32 | *sync/ 33 | Icon? 34 | .tags* 35 | 36 | /Flutter/app.flx 37 | /Flutter/app.zip 38 | /Flutter/flutter_assets/ 39 | /Flutter/App.framework 40 | /Flutter/Flutter.framework 41 | /Flutter/Generated.xcconfig 42 | /ServiceDefinitions.json 43 | 44 | Pods/ 45 | .symlinks/ 46 | -------------------------------------------------------------------------------- /server/src/main/java/com/rowan/ruber/model/google_maps/GeoencodingResult.java: -------------------------------------------------------------------------------- 1 | 2 | package com.rowan.ruber.model.google_maps; 3 | 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | 7 | /** 8 | * Result from the Google Maps Geoencoding API that converts a string address to latitude and longitude 9 | */ 10 | public class GeoencodingResult { 11 | 12 | private List results; 13 | private String status; 14 | 15 | public GeoencodingResult() { 16 | results = new ArrayList<>(); 17 | } 18 | 19 | public List getResults() { 20 | return results; 21 | } 22 | 23 | public void setResults(List results) { 24 | this.results = results; 25 | } 26 | 27 | public String getStatus() { 28 | return status; 29 | } 30 | 31 | public void setStatus(String status) { 32 | this.status = status; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /ruber/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 | -------------------------------------------------------------------------------- /server/src/main/java/com/rowan/ruber/model/google_maps/AddressComponent.java: -------------------------------------------------------------------------------- 1 | 2 | package com.rowan.ruber.model.google_maps; 3 | 4 | import java.util.List; 5 | 6 | public class AddressComponent { 7 | 8 | private String longName; 9 | private String shortName; 10 | private List types; 11 | 12 | public AddressComponent() { 13 | } 14 | 15 | public String getLongName() { 16 | return longName; 17 | } 18 | 19 | public void setLongName(String longName) { 20 | this.longName = longName; 21 | } 22 | 23 | public String getShortName() { 24 | return shortName; 25 | } 26 | 27 | public void setShortName(String shortName) { 28 | this.shortName = shortName; 29 | } 30 | 31 | public List getTypes() { 32 | return types; 33 | } 34 | 35 | public void setTypes(List types) { 36 | this.types = types; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /ruber/lib/UserModel.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | //Takes in a NewUser object and returns a JSON String 4 | String userToJson(NewUser data) { 5 | final dyn = data.toJson(); 6 | return json.encode(dyn); 7 | } 8 | 9 | //Takes in a JSON String and converts it to a NewUser object 10 | NewUser userFromJson(String str) { 11 | final jsonData = json.decode(str); 12 | return NewUser.fromJson(jsonData); 13 | } 14 | 15 | //Class that handles the creation of a new user 16 | class NewUser { 17 | String name; 18 | String email; 19 | 20 | //Constructor for NewUser has a name and email 21 | NewUser({ 22 | this.name, 23 | this.email, 24 | }); 25 | 26 | //Converts the JSON to a NewUser 27 | factory NewUser.fromJson(Map parsedJson) { 28 | return NewUser( 29 | name: parsedJson["name"], 30 | email: parsedJson["email"], 31 | ); 32 | } 33 | 34 | //Converts the data to JSON 35 | Map toJson() => { 36 | "name": name, 37 | "email": email, 38 | }; 39 | } -------------------------------------------------------------------------------- /server/src/main/java/com/rowan/ruber/model/google_maps/Geometry.java: -------------------------------------------------------------------------------- 1 | 2 | package com.rowan.ruber.model.google_maps; 3 | 4 | public class Geometry { 5 | 6 | private Bounds bounds; 7 | private Location location; 8 | private String locationType; 9 | private Viewport viewport; 10 | 11 | public Bounds getBounds() { 12 | return bounds; 13 | } 14 | 15 | public void setBounds(Bounds bounds) { 16 | this.bounds = bounds; 17 | } 18 | 19 | public Location getLocation() { 20 | return location; 21 | } 22 | 23 | public void setLocation(Location location) { 24 | this.location = location; 25 | } 26 | 27 | public String getLocationType() { 28 | return locationType; 29 | } 30 | 31 | public void setLocationType(String locationType) { 32 | this.locationType = locationType; 33 | } 34 | 35 | public Viewport getViewport() { 36 | return viewport; 37 | } 38 | 39 | public void setViewport(Viewport viewport) { 40 | this.viewport = viewport; 41 | } 42 | 43 | 44 | } 45 | -------------------------------------------------------------------------------- /server/src/main/java/com/rowan/ruber/MapsManager.java: -------------------------------------------------------------------------------- 1 | package com.rowan.ruber; 2 | 3 | import com.rowan.ruber.model.google_maps.GeoencodingResult; 4 | import com.rowan.ruber.model.google_maps.Location; 5 | import org.springframework.web.client.RestTemplate; 6 | 7 | public class MapsManager { 8 | 9 | // If you are reading this after December 2018, our API key has been deactivated 10 | // To reactivate this API key, please send me your credit card info 🙂 11 | private static String API_KEY = "AIzaSyBUWTvOdjkdIur2IFzkEPCVTodoL7xUzJk"; 12 | 13 | /** 14 | * Use the geoencoding api from google to convert the user's address in to latitude and longitude 15 | */ 16 | public static Location getCoordinatesFromAddress(String address) { 17 | String url = "https://maps.googleapis.com/maps/api/geocode/json?key=" + API_KEY + "&address=" + address; 18 | 19 | RestTemplate restTemplate = new RestTemplate(); 20 | GeoencodingResult geoencodingResult = restTemplate.getForObject(url, GeoencodingResult.class); 21 | 22 | return geoencodingResult.getResults().get(0).getGeometry().getLocation(); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /ruber/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.2.51' 3 | repositories { 4 | google() 5 | jcenter() 6 | } 7 | 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:3.1.0' 10 | classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.2.50' 11 | classpath 'com.google.gms:google-services:3.1.2' 12 | } 13 | } 14 | 15 | allprojects { 16 | repositories { 17 | google() 18 | maven { url 'http://repo1.maven.org/maven2' } 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 | subprojects { 30 | project.configurations.all { 31 | resolutionStrategy.eachDependency { details -> 32 | if (details.requested.group == 'com.android.support' 33 | && !details.requested.name.contains('multidex') ) { 34 | details.useVersion "26.1.0" 35 | } 36 | } 37 | } 38 | } 39 | 40 | task clean(type: Delete) { 41 | delete rootProject.buildDir 42 | } -------------------------------------------------------------------------------- /server/src/main/java/com/rowan/ruber/Authenticator.java: -------------------------------------------------------------------------------- 1 | package com.rowan.ruber; 2 | 3 | import com.google.auth.oauth2.GoogleCredentials; 4 | import com.google.firebase.FirebaseApp; 5 | import com.google.firebase.FirebaseOptions; 6 | import com.google.firebase.auth.FirebaseAuth; 7 | import com.google.firebase.auth.FirebaseAuthException; 8 | import com.google.firebase.auth.FirebaseToken; 9 | 10 | import java.io.IOException; 11 | 12 | public class Authenticator { 13 | 14 | /** 15 | * Sign a user in to the app given their auth token 16 | */ 17 | public String authenticate(String authToken) { 18 | try { 19 | FirebaseOptions options = new FirebaseOptions.Builder() 20 | .setCredentials(GoogleCredentials.fromStream(Utils.convertStringToStream(Ids.FIREBASE_AUTH_KEY))) 21 | .setDatabaseUrl("https://rowan-carpool.firebaseio.com") 22 | .build(); 23 | 24 | FirebaseApp.initializeApp(options); 25 | 26 | FirebaseToken decodedToken = FirebaseAuth.getInstance().verifyIdToken(authToken); 27 | //String uid = decodedToken.getUid(); 28 | 29 | return decodedToken.getName(); 30 | } catch (FirebaseAuthException | IOException e) { 31 | // Invalid auth token 32 | return null; 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /server/src/main/java/com/rowan/ruber/model/Day.java: -------------------------------------------------------------------------------- 1 | package com.rowan.ruber.model; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Enumerated Type to represent the days of the week. Used for Schedule. 7 | */ 8 | public enum Day implements Serializable { 9 | MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY; 10 | 11 | public static Day fromInteger(int x) { 12 | switch(x) { 13 | case 0: 14 | return MONDAY; 15 | case 1: 16 | return TUESDAY; 17 | case 2: 18 | return WEDNESDAY; 19 | case 3: 20 | return THURSDAY; 21 | case 4: 22 | return FRIDAY; 23 | case 5: 24 | return SATURDAY; 25 | case 6: 26 | return SUNDAY; 27 | default: 28 | return null; 29 | } 30 | } 31 | 32 | public static char toCharacter(Day d) 33 | { 34 | switch(d){ 35 | case MONDAY: 36 | return 'M'; 37 | case TUESDAY: 38 | return 'T'; 39 | case WEDNESDAY: 40 | return 'W'; 41 | case THURSDAY: 42 | return 'R'; 43 | case FRIDAY: 44 | return 'F'; 45 | case SATURDAY: 46 | return 'S'; 47 | case SUNDAY: 48 | return 'U'; 49 | default: 50 | return ' '; 51 | 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /ruber/lib/AddressPostModel.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | //Takes in a JSON String and converts it an AddressPost object 4 | AddressPost addressFromJson(String str) { 5 | final jsonData = json.decode(str); 6 | return AddressPost.fromJson(jsonData); 7 | } 8 | 9 | //Takes in an AddressPost object and returns a JSON String 10 | String addressPostToJson(AddressPost data) { 11 | final dyn = data.toJson(); 12 | return json.encode(dyn); 13 | } 14 | 15 | //Returns a list of all AddressPost's from a JSON String 16 | List allAddressesFromJson(String str) { 17 | final jsonData = json.decode(str); 18 | return new List.from( 19 | jsonData.map((x) => AddressPost.fromJson(x))); 20 | } 21 | 22 | //Class that makes up what is required to post an Address 23 | class AddressPost { 24 | String streetAddress; 25 | String city; 26 | String zipCode; 27 | String state; 28 | 29 | //Constructor for an AddressPost object 30 | AddressPost({ 31 | this.streetAddress, 32 | this.city, 33 | this.zipCode, 34 | this.state, 35 | }); 36 | 37 | //Converts the JSON to an AddressPost 38 | factory AddressPost.fromJson(Map parsedJson) { 39 | return AddressPost( 40 | streetAddress: parsedJson["streetAddress"], 41 | city: parsedJson["city"], 42 | zipCode: parsedJson["zipCode"], 43 | state: parsedJson["state"], 44 | ); 45 | } 46 | 47 | //Converts the data to JSON 48 | Map toJson() => { 49 | "streetAddress": streetAddress, 50 | "city": city, 51 | "zipCode": zipCode, 52 | "state": state, 53 | }; 54 | } -------------------------------------------------------------------------------- /server/src/main/java/com/rowan/ruber/model/google_maps/Result.java: -------------------------------------------------------------------------------- 1 | 2 | package com.rowan.ruber.model.google_maps; 3 | 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | 7 | public class Result { 8 | 9 | private List addressComponents; 10 | private String formattedAddress; 11 | private Geometry geometry; 12 | private String placeId; 13 | private List types; 14 | 15 | public Result() { 16 | addressComponents = new ArrayList<>(); 17 | types = new ArrayList<>(); 18 | } 19 | 20 | public List getAddressComponents() { 21 | return addressComponents; 22 | } 23 | 24 | public void setAddressComponents(List addressComponents) { 25 | this.addressComponents = addressComponents; 26 | } 27 | 28 | public String getFormattedAddress() { 29 | return formattedAddress; 30 | } 31 | 32 | public void setFormattedAddress(String formattedAddress) { 33 | this.formattedAddress = formattedAddress; 34 | } 35 | 36 | public Geometry getGeometry() { 37 | return geometry; 38 | } 39 | 40 | public void setGeometry(Geometry geometry) { 41 | this.geometry = geometry; 42 | } 43 | 44 | public String getPlaceId() { 45 | return placeId; 46 | } 47 | 48 | public void setPlaceId(String placeId) { 49 | this.placeId = placeId; 50 | } 51 | 52 | public List getTypes() { 53 | return types; 54 | } 55 | 56 | public void setTypes(List types) { 57 | this.types = types; 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /ruber/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 | -------------------------------------------------------------------------------- /ruber/android/app/google-services.json: -------------------------------------------------------------------------------- 1 | { 2 | "project_info": { 3 | "project_number": "595426910927", 4 | "firebase_url": "https://rowan-carpool.firebaseio.com", 5 | "project_id": "rowan-carpool", 6 | "storage_bucket": "rowan-carpool.appspot.com" 7 | }, 8 | "client": [ 9 | { 10 | "client_info": { 11 | "mobilesdk_app_id": "1:595426910927:android:135ac0c60058b625", 12 | "android_client_info": { 13 | "package_name": "com.ruber.ruber" 14 | } 15 | }, 16 | "oauth_client": [ 17 | { 18 | "client_id": "595426910927-pvceg8im0ptob1vdg8f4bcf3k36g13sa.apps.googleusercontent.com", 19 | "client_type": 1, 20 | "android_info": { 21 | "package_name": "com.ruber.ruber", 22 | "certificate_hash": "d428766354982cbbec770baab9bfcc2db1162ac7" 23 | } 24 | }, 25 | { 26 | "client_id": "595426910927-5u3ojfnkcb9gigj5n78temrrij09rdug.apps.googleusercontent.com", 27 | "client_type": 3 28 | } 29 | ], 30 | "api_key": [ 31 | { 32 | "current_key": "AIzaSyDtlp3t9GtTVaIqWup2fCltMNrX3yeN2uo" 33 | } 34 | ], 35 | "services": { 36 | "analytics_service": { 37 | "status": 1 38 | }, 39 | "appinvite_service": { 40 | "status": 2, 41 | "other_platform_oauth_client": [ 42 | { 43 | "client_id": "595426910927-5u3ojfnkcb9gigj5n78temrrij09rdug.apps.googleusercontent.com", 44 | "client_type": 3 45 | } 46 | ] 47 | }, 48 | "ads_service": { 49 | "status": 2 50 | } 51 | } 52 | } 53 | ], 54 | "configuration_version": "1" 55 | } -------------------------------------------------------------------------------- /ruber/ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSLocationWhenInUseUsageDescription 6 | Using location to display on a map 7 | CFBundleDevelopmentRegion 8 | en 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ruber 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 | 47 | 48 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Ryde 2 | 3 | The purpose of our app is to help students find other students who also commute to Rowan and live in the same general area as they do. This is done by showing how many Rowan students live in the user's specified radius and what their schedules are. From there, either person can contact the other to set up a carpooling schedule. 4 | 5 | Made using Flutter, Spring Boot (Java), and MySQL 6 | 7 | Authors: [Nicholas La Sala](https://github.com/ncklasala), [Wen Cao](https://github.com/caow2), [Michael Matthews](https://github.com/pro452), [Benny Chen](https://github.com/chenb7), [Tapan Soni](https://github.com/TapanSoni), [Tyler Carberry](https://github.com/TylerCarberry), [Benny Liang](https://github.com/liangb6), and [John Stranahan](https://github.com/JohnStranahan) 8 | Scrum Master: [John Stranahan](https://github.com/JohnStranahan) 9 | 10 | ### Documents 11 | [Project Specification Document](https://github.com/TylerCarberry/RowanRideshare/files/2573418/Project.Spec.pdf) 12 | [Design Document](https://github.com/TylerCarberry/RowanRideshare/files/2573413/Design.Document.1.pdf) 13 | 14 | ### Screenshots 15 | Home Schedule Matches 16 | 17 | 18 | 19 | ### [Demo Video](https://drive.google.com/file/d/1miveKWpqok4fH83gyjjVsXeti8FP_TRW/view?usp=sharing) 20 | [![Watch the video](https://user-images.githubusercontent.com/6628497/50185048-c73d6780-02e4-11e9-9cd7-7b91c1bad3db.png)](https://drive.google.com/file/d/1miveKWpqok4fH83gyjjVsXeti8FP_TRW/view?usp=sharing) 21 | -------------------------------------------------------------------------------- /ruber/lib/MessageModel.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | //Takes in a JSON string and converts it to a Message object 4 | Message messageFromJson(String str) { 5 | final jsonData = json.decode(str); 6 | return Message.fromJson(jsonData); 7 | } 8 | 9 | //Takes in a Message object and returns a JSON String 10 | String messageToJson(Message data) { 11 | final dyn = data.toJson(); 12 | return json.encode(dyn); 13 | } 14 | 15 | //Returns a list of all Messages from a JSON String 16 | List allMessagesFromJson(String str) { 17 | final jsonData = json.decode(str); 18 | return new List.from(jsonData.map((x) => Message.fromJson(x))); 19 | } 20 | 21 | //Converts a List of Messages to a Json String 22 | String allMessagessToJson(List data) { 23 | final dyn = new List.from(data.map((x) => x.toJson())); 24 | return json.encode(dyn); 25 | } 26 | 27 | //Class that creates a Message object that allows users to communicate 28 | class Message { 29 | int id; 30 | var chatroom; 31 | int senderID; 32 | String text; 33 | var timeSent; 34 | 35 | //Constructor for a Message that has id, chatroom, senderID, text, and timeSent 36 | Message({ 37 | this.id, 38 | this.chatroom, 39 | this.senderID, 40 | this.text, 41 | this.timeSent, 42 | }); 43 | 44 | //Converts a JSON to a Message 45 | factory Message.fromJson(Map parsedJson) { 46 | return Message( 47 | id: parsedJson["id"], 48 | chatroom: parsedJson["chatroom"], 49 | senderID: parsedJson["senderID"], 50 | text: parsedJson["text"], 51 | timeSent: parsedJson["timeSent"], 52 | ); 53 | } 54 | 55 | //Converts the data to JSON 56 | Map toJson() => { 57 | "id": id, 58 | "chatroom": chatroom, 59 | "senderID": senderID, 60 | "text": text, 61 | "timeSent": timeSent, 62 | }; 63 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | .DS_Store 3 | 4 | ruber/\.idea/workspace\.xml 5 | 6 | ruber/ios/Podfile 7 | 8 | # Miscellaneous 9 | *.class 10 | *.lock 11 | *.log 12 | *.pyc 13 | *.swp 14 | .DS_Store 15 | .atom/ 16 | .buildlog/ 17 | .history 18 | .svn/ 19 | 20 | # IntelliJ related 21 | *.iml 22 | *.ipr 23 | *.iws 24 | .idea/ 25 | 26 | # Visual Studio Code related 27 | .vscode/ 28 | 29 | # Flutter repo-specific 30 | /bin/cache/ 31 | /bin/mingit/ 32 | /dev/benchmarks/mega_gallery/ 33 | /dev/bots/.recipe_deps 34 | /dev/bots/android_tools/ 35 | /dev/docs/doc/ 36 | /dev/docs/lib/ 37 | /dev/docs/pubspec.yaml 38 | /packages/flutter/coverage/ 39 | version 40 | 41 | # Flutter/Dart/Pub related 42 | **/doc/api/ 43 | .dart_tool/ 44 | .flutter-plugins 45 | .packages 46 | .pub-cache/ 47 | .pub/ 48 | build/ 49 | flutter_*.png 50 | linked_*.ds 51 | unlinked.ds 52 | unlinked_spec.ds 53 | 54 | # Android related 55 | **/android/**/gradle-wrapper.jar 56 | **/android/.gradle 57 | **/android/captures/ 58 | **/android/gradlew 59 | **/android/gradlew.bat 60 | **/android/local.properties 61 | **/android/**/GeneratedPluginRegistrant.java 62 | 63 | # iOS/XCode related 64 | **/ios/**/*.mode1v3 65 | **/ios/**/*.mode2v3 66 | **/ios/**/*.moved-aside 67 | **/ios/**/*.pbxuser 68 | **/ios/**/*.perspectivev3 69 | **/ios/**/*sync/ 70 | **/ios/**/.sconsign.dblite 71 | **/ios/**/.tags* 72 | **/ios/**/.vagrant/ 73 | **/ios/**/DerivedData/ 74 | **/ios/**/Icon? 75 | **/ios/**/Pods/ 76 | **/ios/**/.symlinks/ 77 | **/ios/**/profile 78 | **/ios/**/xcuserdata 79 | **/ios/.generated/ 80 | **/ios/Flutter/App.framework 81 | **/ios/Flutter/Flutter.framework 82 | **/ios/Flutter/Generated.xcconfig 83 | **/ios/Flutter/app.flx 84 | **/ios/Flutter/app.zip 85 | **/ios/Flutter/flutter_assets/ 86 | **/ios/ServiceDefinitions.json 87 | **/ios/Runner/GeneratedPluginRegistrant.* 88 | 89 | # Exceptions to above rules. 90 | !**/ios/**/default.mode1v3 91 | !**/ios/**/default.mode2v3 92 | !**/ios/**/default.pbxuser 93 | !**/ios/**/default.perspectivev3 94 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 95 | /bin/ 96 | -------------------------------------------------------------------------------- /ruber/lib/GoingToRowan.dart: -------------------------------------------------------------------------------- 1 | /// GoingToRowan.dart 2 | /// 3 | /// Purpose: 4 | /// The purpose of this file is to provide the radius 5 | /// variables to the screen where the user selects the 6 | /// radius for searching. 7 | 8 | import 'package:flutter/material.dart'; 9 | import 'package:shared_preferences/shared_preferences.dart'; 10 | import 'AppDrawer.dart'; 11 | 12 | double radius = 0; 13 | 14 | getRadius() { 15 | return radius.toInt(); 16 | } 17 | 18 | class goingtorowan extends StatefulWidget { 19 | @override 20 | _gtr createState() => new _gtr(); 21 | } 22 | 23 | setRadius(int radius) async { 24 | SharedPreferences prefs = await SharedPreferences.getInstance(); 25 | prefs.setInt("radius", radius); 26 | } 27 | 28 | class _gtr extends State { 29 | void _setRadius(double newValue) => setState(() => radius = newValue); 30 | 31 | @override 32 | Widget build(BuildContext context) { 33 | return Scaffold( 34 | appBar: AppBar( 35 | title: Text("Going to Rowan"), 36 | centerTitle: true, 37 | ), 38 | drawer: launchAppDrawer(context), 39 | body: Column( 40 | mainAxisAlignment: MainAxisAlignment.spaceEvenly, 41 | children: [ 42 | Text('Select the radius for searching', 43 | style: TextStyle( 44 | color: Colors.lightBlueAccent, 45 | fontSize: 23.0, 46 | fontWeight: FontWeight.bold)), 47 | Text( 48 | 'Radius: ${radius.toInt()} miles', 49 | style: TextStyle(fontSize: 18.0, fontWeight: FontWeight.bold), 50 | ), 51 | Slider( 52 | value: radius, 53 | min: 0, 54 | max: 20, 55 | onChanged: _setRadius, 56 | ), 57 | RaisedButton( 58 | child: Text('Find Rides!'), 59 | onPressed: () { 60 | print("Hello"); 61 | }, 62 | ) 63 | ], 64 | )); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /ruber/lib/ScheduleModel.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | //Takes in a JSON string and converts it to a NewUser object 4 | Schedule scheduleFromJson(String str) { 5 | final jsonData = json.decode(str); 6 | return Schedule.fromJson(jsonData); 7 | } 8 | 9 | //Takes in a Schedule object and returns a JSON String 10 | String scheduleToJson(Schedule data) { 11 | final dyn = data.toJson(); 12 | return json.encode(dyn); 13 | } 14 | 15 | //Returns a list of all Schedules from a JSON String 16 | List allSchedulesFromJson(String str) { 17 | final jsonData = json.decode(str); 18 | return new List.from(jsonData.map((x) => Schedule.fromJson(x))); 19 | } 20 | 21 | //Converts a List of schedules to a JSON String 22 | String allScheduleToJson(List data) { 23 | final dyn = new List.from(data.map((x) => x.toJson())); 24 | return json.encode(dyn); 25 | } 26 | 27 | //Class that creates a Schedule object and allows converting and parsing the data 28 | class Schedule { 29 | int id; 30 | int profile; 31 | String monday; 32 | String tuesday; 33 | String wednesday; 34 | String thursday; 35 | String friday; 36 | 37 | //Constructor for Schedule has id, profile, and days of the week 38 | Schedule({ 39 | this.id, 40 | this.profile, 41 | this.monday, 42 | this.tuesday, 43 | this.wednesday, 44 | this.thursday, 45 | this.friday, 46 | }); 47 | 48 | //Converts the JSON to a NewUser 49 | factory Schedule.fromJson(Map parsedJson) { 50 | return Schedule( 51 | id: parsedJson["id"], 52 | profile: parsedJson["profile"], 53 | monday: parsedJson["monday"], 54 | tuesday: parsedJson["tuesday"], 55 | wednesday: parsedJson["wednesday"], 56 | thursday: parsedJson["thursday"], 57 | friday: parsedJson["friday"], 58 | ); 59 | } 60 | 61 | //Converts the data to JSON 62 | Map toJson() => { 63 | "id": id, 64 | "profile": profile, 65 | "monday": monday, 66 | "tuesday": tuesday, 67 | "wednesday": wednesday, 68 | "thursday": thursday, 69 | "friday": friday 70 | }; 71 | } -------------------------------------------------------------------------------- /server/bin/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.rowan 7 | ruber 8 | 0.0.1-SNAPSHOT 9 | jar 10 | 11 | ruber 12 | Demo project for Spring Boot 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 2.0.5.RELEASE 18 | 19 | 20 | 21 | 22 | UTF-8 23 | UTF-8 24 | 1.8 25 | 26 | 27 | 28 | 29 | org.springframework.boot 30 | spring-boot-starter 31 | 32 | 33 | 34 | mysql 35 | mysql-connector-java 36 | runtime 37 | 38 | 39 | org.springframework.boot 40 | spring-boot-starter-test 41 | test 42 | 43 | 44 | org.springframework.boot 45 | spring-boot-starter-web 46 | RELEASE 47 | compile 48 | 49 | 50 | com.google.firebase 51 | firebase-admin 52 | 6.5.0 53 | 54 | 55 | 56 | 57 | 58 | 59 | org.springframework.boot 60 | spring-boot-maven-plugin 61 | 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /ruber/lib/AddressModel.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | /* 4 | The address model holds the information of a persons address 5 | This includes the following information: 6 | street address, city, zip, state, longitude, latitude 7 | */ 8 | 9 | // Returns an address object 10 | Address addressFromJson(String str) { 11 | final jsonData = json.decode(str); 12 | return Address.fromJson(jsonData); 13 | } 14 | 15 | // Returns a String 16 | String addressToJson(Address data) { 17 | final dyn = data.toJson(); 18 | return json.encode(dyn); 19 | } 20 | 21 | //Returns a List of Address objects from JSON String 22 | List
allAddressesFromJson(String str) { 23 | final jsonData = json.decode(str); 24 | return new List
.from(jsonData.map((x) => Address.fromJson(x))); 25 | } 26 | 27 | String allAddressesToJson(List
data) { 28 | final dyn = new List.from(data.map((x) => x.toJson())); 29 | return json.encode(dyn); 30 | } 31 | 32 | //Class that makes up what is required to get an Address 33 | class Address { 34 | int id; 35 | String streetAddress; 36 | String city; 37 | String zipCode; 38 | String state; 39 | double latitude; 40 | double longitude; 41 | 42 | //Constructor for an Address object 43 | Address({ 44 | this.id, 45 | this.streetAddress, 46 | this.city, 47 | this.zipCode, 48 | this.state, 49 | this.latitude, 50 | this.longitude, 51 | }); 52 | 53 | //Converts the JSON to an Address 54 | factory Address.fromJson(Map parsedJson) { 55 | return Address( 56 | id: parsedJson["id"], 57 | streetAddress: parsedJson["streetAddress"], 58 | city: parsedJson["city"], 59 | zipCode: parsedJson["zipCode"], 60 | state: parsedJson["state"], 61 | latitude: parsedJson["latitude"], 62 | longitude: parsedJson["longitude"], 63 | ); 64 | } 65 | 66 | //Converts the data to JSON 67 | Map toJson() => { 68 | "id": id, 69 | "streetAddress": streetAddress, 70 | "city": city, 71 | "zipCode": zipCode, 72 | "state": state, 73 | "latitude": latitude, 74 | "longitude": longitude, 75 | }; 76 | 77 | @override 78 | String toString() { 79 | return id.toString() + streetAddress.toString() + city + zipCode + state; 80 | } 81 | } -------------------------------------------------------------------------------- /ruber/lib/RideScreen.dart: -------------------------------------------------------------------------------- 1 | /// RideScreen.dart 2 | /// 3 | /// Purpose: 4 | /// The purpose of this file is to provide the user with a radius slider 5 | /// which is used to select the search radius for ride matching. It is 6 | /// preset to 20 miles, but we can change that. From this screen, it takes 7 | /// the user to the matches screen. 8 | 9 | /// Imports 10 | import 'package:flutter/material.dart'; 11 | import 'package:shared_preferences/shared_preferences.dart'; 12 | 13 | import 'AppDrawer.dart'; 14 | import 'GoingToRowan.dart'; 15 | import 'matches_screen.dart'; 16 | 17 | class launchRideScreen extends StatefulWidget { 18 | @override 19 | _gtr createState() => new _gtr(); 20 | } 21 | 22 | saveRadius(double radius) async { 23 | SharedPreferences prefs = await SharedPreferences.getInstance(); 24 | prefs.setInt("radius", radius.toInt()); 25 | } 26 | 27 | class _gtr extends State { 28 | void _setRadius(double newValue) => setState(() => radius = newValue); 29 | 30 | @override 31 | Widget build(BuildContext context) { 32 | return Scaffold( 33 | appBar: AppBar( 34 | title: Text("New Ride"), 35 | centerTitle: true, 36 | ), 37 | drawer: launchAppDrawer(context), 38 | body: Column( 39 | mainAxisAlignment: MainAxisAlignment.spaceEvenly, 40 | children: [ 41 | Text('Select the radius for searching', 42 | style: TextStyle( 43 | color: Colors.blue, 44 | fontSize: 23.0, 45 | fontWeight: FontWeight.bold)), 46 | Text( 47 | 'Radius: ${radius.toInt()} miles', 48 | style: TextStyle(fontSize: 18.0, fontWeight: FontWeight.bold), 49 | ), 50 | Slider( 51 | value: radius, 52 | min: 0, // Set the min to 0 miles 53 | max: 20, // Set the max to 20 miles 54 | onChanged: _setRadius, 55 | ), 56 | RaisedButton( 57 | child: Text('Find Rides!'), 58 | color: Colors.blue, 59 | textColor: Colors.white, 60 | onPressed: () { 61 | saveRadius(radius); 62 | Navigator.push(context, 63 | MaterialPageRoute(builder: (context) => matchesScreen())); 64 | }, 65 | ) 66 | ], 67 | )); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /ruber/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 | 28 | android { 29 | compileSdkVersion 27 30 | 31 | sourceSets { 32 | main.java.srcDirs += 'src/main/kotlin' 33 | } 34 | 35 | lintOptions { 36 | disable 'InvalidPackage' 37 | } 38 | 39 | defaultConfig { 40 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 41 | applicationId "com.ruber.ruber" 42 | minSdkVersion 16 43 | targetSdkVersion 27 44 | versionCode flutterVersionCode.toInteger() 45 | versionName flutterVersionName 46 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 47 | } 48 | 49 | buildTypes { 50 | release { 51 | // TODO: Add your own signing config for the release build. 52 | // Signing with the debug keys for now, so `flutter run --release` works. 53 | signingConfig signingConfigs.debug 54 | } 55 | } 56 | } 57 | 58 | flutter { 59 | source '../..' 60 | } 61 | 62 | dependencies { 63 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version" 64 | testImplementation 'junit:junit:4.12' 65 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 66 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 67 | implementation 'com.google.firebase:firebase-core:16.0.4' 68 | } 69 | 70 | apply plugin: 'com.google.gms.google-services' -------------------------------------------------------------------------------- /server/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.rowan 7 | ruber 8 | 0.0.1-SNAPSHOT 9 | jar 10 | 11 | ruber 12 | Demo project for Spring Boot 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 2.0.5.RELEASE 18 | 19 | 20 | 21 | 22 | UTF-8 23 | UTF-8 24 | 1.8 25 | 26 | 27 | 28 | 29 | org.springframework.boot 30 | spring-boot-starter 31 | 32 | 33 | 34 | mysql 35 | mysql-connector-java 36 | runtime 37 | 38 | 39 | 40 | org.springframework.boot 41 | spring-boot-starter-test 42 | test 43 | 44 | 45 | 46 | org.springframework.boot 47 | spring-boot-starter-web 48 | RELEASE 49 | compile 50 | 51 | 52 | 53 | com.google.firebase 54 | firebase-admin 55 | 6.5.0 56 | 57 | 58 | 59 | javax.xml.bind 60 | jaxb-api 61 | 2.3.0 62 | 63 | 64 | 65 | org.springframework.boot 66 | spring-boot-starter-data-jpa 67 | 2.0.6.RELEASE 68 | 69 | 70 | 71 | 72 | 73 | 74 | org.springframework.boot 75 | spring-boot-maven-plugin 76 | 77 | 78 | 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /ruber/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 | -------------------------------------------------------------------------------- /ruber/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 8 | 9 | 10 | 11 | 12 | 17 | 21 | 22 | 23 | 30 | 34 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /server/src/main/java/com/rowan/ruber/Ids.java: -------------------------------------------------------------------------------- 1 | package com.rowan.ruber; 2 | 3 | public class Ids { 4 | 5 | public static final String FIREBASE_AUTH_KEY = "{\n" + 6 | " \"type\": \"service_account\",\n" + 7 | " \"project_id\": \"rowan-carpool\",\n" + 8 | " \"private_key_id\": \"e81b414d7cee3c3d6989cd77ca7957482e0b92c0\",\n" + 9 | " \"private_key\": \"-----BEGIN PRIVATE KEY-----\\nMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCx9MIafuOcrZvn\\nBJ6/dXuPag5vTjjnkeeUlHk3BWBVVF/tBHOneaL/dRK7uySBIlsPet5+Ki8peFqO\\n1F1wgQaBoUEPhbfniSjmpEekoCND127DVXD1gg3pNx/8XJimgVxOWxAnQx6jGQbw\\n+lhKcCb2i1mRTqLL/7DAffOJyBMIKW4uIMrNixQtr7xFFW+2V6smtVmtEDKxTJpm\\nrQQWbOz62fmxZgIsEqQyBQqlwp7XNvr1yvx4lhf73bdSHgSWKKqB1Ftt7pDPCqbt\\n/2Bq93bQzKTt3rK85SmcnS7O3wtqd+NvMOjQHkdqZbokxBT2Ubj8WbG9hhl5woPw\\nVk1B0KP1AgMBAAECggEADiWDaADN+PlnddoiVoexLrRDI9UHkAfDbZvPS7Dujgn6\\n5YgfkODfX3MVQ1LmstSiLDJbzT1u6gXfyQ/tF6b3d0b0OZbV3kmYifE6+BrPgt1K\\n4wCqo1Gskm1n6l4Kt93REoeJsAgAFP4bKlKfFy0gOSQtwW/gtYUvg2CKg4RMra7J\\n7MTZliXfYJMclubaiKnOLxEaAtvM31tzgi8hUspIHGYzudiOkVbht9yKuJpjXsJg\\ndTZSHs1TtARxqteBhk/KcHC+aeAw6yzH8jmatEN78EyXHcLOzJbcYBHvLW+Ep6Tl\\nem74dhxK48fOcn4QqWFUMIGHspsJbbm91S8EAvXP5wKBgQDyHp2sxYJAwEKZVWGS\\ntBM3596gy1cCe/YSLqYIgvxOG+Kd+oogUvHdrxP3mDvnNZOjkeMDvIQtmkjlQYo5\\nHoqEJOvbyrkJwopn3uKGG65lqGmYXaZfkYeeoxdxrvyRiwmPQwtlGLT7H8Ci5KuC\\nWZswIAn0wJE2Ijj6zG34r49YnwKBgQC8KHgJH5LR8p1waOEbJqlvm3t6QeuEyIGf\\n2PaaYputqz/pjnhXZBekIsQiQP4l7jDdNGJj8oifx/xN0h1Wk8hnffHEq5tE9PIo\\nhVX8uIu6nLHctd0D/ztUCr8UIz/K5rvOE09T6u+ujByGioXZA1RnJM23uUQQVt2T\\nLzd5QP926wKBgCFUsaQdNIcxcHmnVV1ayOKDWxSLqZi/8+og3d6CGbWvBQ12dhlp\\nEb7Q4VDOdkCoEYENDlFvXEri2HInCZ4/ZBY49vc0+zAqxd7ywgBwQxvfiVneWo8B\\ne8gM76dIzaBDobdFJYZvVkrT3jMOg8XYDBMd9gDpmZP4NhvglKsNkBBFAoGAIKQA\\nlsyUYrls2HhJPLWLRSI63G2dFs7Vtc4kkYmzqgAAOVsOw1JIy5+AWNTfgeL9NRKG\\nUwJa8yT1PubJUiCW7mUp0M1YRTEc5SykSxAUpU3TiQ8/hRb8ysqGdU7cHS3DvK8a\\n3trts2D4/dn/+DKcrLv0t/96sD7xdzwEqpM8/fsCgYArxO8bUOo3KuZ8MpbT4eeW\\nulSYkH4YtAMjWOiLkaamzzg46Nh5TRV0IDCHQPlib7tH2+e+AHtvC51DoB1WF9Hx\\nW9C+L8EI9mqqWxpu4Y/F0Nwc7PK+FnEyMyQgVu34Sk97zwoMHk9DTTcy6xTJXRQl\\nozm7NLx8rrCwA4MwqhR5Jw==\\n-----END PRIVATE KEY-----\\n\",\n" + 10 | " \"client_email\": \"firebase-adminsdk-jy4h4@rowan-carpool.iam.gserviceaccount.com\",\n" + 11 | " \"client_id\": \"106417927546032867975\",\n" + 12 | " \"auth_uri\": \"https://accounts.google.com/o/oauth2/auth\",\n" + 13 | " \"token_uri\": \"https://oauth2.googleapis.com/token\",\n" + 14 | " \"auth_provider_x509_cert_url\": \"https://www.googleapis.com/oauth2/v1/certs\",\n" + 15 | " \"client_x509_cert_url\": \"https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-jy4h4%40rowan-carpool.iam.gserviceaccount.com\"\n" + 16 | "}\n"; 17 | 18 | } 19 | -------------------------------------------------------------------------------- /ruber/lib/AppDrawer.dart: -------------------------------------------------------------------------------- 1 | /// AppDrawer.dart 2 | /// 3 | /// Purpose: 4 | /// This file is used for the app drawer in flutter 5 | /// It shows a menu whenever the user clicks on the app drawer icon 6 | /// on the top left hand side of the app. 7 | 8 | /// Imports 9 | import 'package:flutter/material.dart'; 10 | 11 | import 'ChatRoomScreen.dart'; 12 | import 'RideScreen.dart'; 13 | import 'editschedule.dart'; 14 | import 'main.dart'; 15 | import 'profile.dart'; 16 | 17 | /// Drawer Widget which holds all the drawer options 18 | /// Drawer Options: 19 | /// 1) Main Screen - MainScreen() 20 | /// 2) New Ryde Screen - launchRideScreen() 21 | /// 3) Messages Screen - ChatRoomScreen() 22 | /// 4) Profile Screen - ProfileScreen() 23 | /// 5) Schedule Screen - ScheduleForm() 24 | Drawer launchAppDrawer(context) { 25 | return Drawer( 26 | child: ListView( 27 | children: [ 28 | DrawerHeader( 29 | child: Image.network( 30 | 'https://www.tlcrentalmarketplace.com/wp-content/uploads/2018/03/rideshare.png', 31 | height: 150, 32 | ), 33 | ), 34 | 35 | /// Main Screen option 36 | 37 | ListTile( 38 | leading: Icon(Icons.home), 39 | title: Text('Main Menu'), 40 | onTap: () { 41 | Navigator.push( 42 | context, 43 | MaterialPageRoute(builder: (context) => MainScreen()), 44 | ); 45 | }, 46 | ), 47 | 48 | /// New Ryde screen option 49 | 50 | ListTile( 51 | leading: Icon(Icons.directions_car), 52 | title: Text('New Ride'), 53 | onTap: () { 54 | Navigator.push(context, 55 | MaterialPageRoute(builder: (context) => launchRideScreen())); 56 | }), 57 | 58 | /// Messages screen option 59 | 60 | ListTile( 61 | leading: Icon(Icons.message), 62 | title: Text('Messages'), 63 | onTap: () { 64 | Navigator.push( 65 | context, 66 | MaterialPageRoute(builder: (context) => ChatRoomScreen()), 67 | ); 68 | }, 69 | ), 70 | 71 | /// Profile screen option 72 | 73 | ListTile( 74 | leading: Icon(Icons.account_box), 75 | title: Text('Profile'), 76 | onTap: () { 77 | Navigator.push( 78 | context, 79 | MaterialPageRoute(builder: (context) => ProfileScreen()), 80 | ); 81 | }, 82 | ), 83 | 84 | /// Schedule screen option 85 | 86 | ListTile( 87 | leading: Icon(Icons.schedule), 88 | title: Text('Schedule'), 89 | onTap: () { 90 | Navigator.push( 91 | context, MaterialPageRoute(builder: (context) => ScheduleForm())); 92 | }, 93 | ), 94 | ], 95 | )); 96 | } 97 | -------------------------------------------------------------------------------- /ruber/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 | -------------------------------------------------------------------------------- /ruber/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: ruber 2 | description: Rowan Carpool 3 | 4 | # The following defines the version and build number for your application. 5 | # A version number is three numbers separated by dots, like 1.2.43 6 | # followed by an optional build number separated by a +. 7 | # Both the version and the builder number may be overridden in flutter 8 | # build by specifying --build-name and --build-number, respectively. 9 | # Read more about versioning at semver.org. 10 | version: 1.0.0+1 11 | 12 | environment: 13 | sdk: ">=2.0.0-dev.68.0 <3.0.0" 14 | 15 | dependencies: 16 | flutter: 17 | sdk: flutter 18 | 19 | # The following adds the Cupertino Icons font to your application. 20 | # Use with the CupertinoIcons class for iOS style icons. 21 | cupertino_icons: ^0.1.2 22 | map_view: 23 | git: 24 | url: git://github.com/Eimji/flutter_google_map_view.git 25 | 26 | http: ^0.12.0 27 | shared_preferences: ^0.4.3 28 | 29 | path_provider: ^0.4.0 30 | 31 | google_sign_in: ^3.2.1 32 | firebase_auth: ^0.6.2+1 33 | 34 | 35 | # For information on the generic Dart part of this file, see the 36 | # following page: https://www.dartlang.org/tools/pub/pubspec 37 | 38 | # The following section is specific to Flutter. 39 | flutter: 40 | assets: 41 | - assets/RowanCampus.jpg 42 | 43 | # The following line ensures that the Material Icons font is 44 | # included with your application, so that you can use the icons in 45 | # the material Icons class. 46 | uses-material-design: true 47 | 48 | # To add assets to your application, add an assets section, like this: 49 | # assets: 50 | # - images/a_dot_burr.jpeg 51 | # - images/a_dot_ham.jpeg 52 | 53 | # An image asset can refer to one or more resolution-specific "variants", see 54 | # https://flutter.io/assets-and-images/#resolution-aware. 55 | 56 | # For details regarding adding assets from package dependencies, see 57 | # https://flutter.io/assets-and-images/#from-packages 58 | 59 | # To add custom fonts to your application, add a fonts section here, 60 | # in this "flutter" section. Each entry in this list should have a 61 | # "family" key with the font family name, and a "fonts" key with a 62 | # list giving the asset and other descriptors for the font. For 63 | # example: 64 | # fonts: 65 | # - family: Schyler 66 | # fonts: 67 | # - asset: fonts/Schyler-Regular.ttf 68 | # - asset: fonts/Schyler-Italic.ttf 69 | # style: italic 70 | # - family: Trajan Pro 71 | # fonts: 72 | # - asset: fonts/TrajanPro.ttf 73 | # - asset: fonts/TrajanPro_Bold.ttf 74 | # weight: 700 75 | # 76 | # For details regarding fonts from package dependencies, 77 | # see https://flutter.io/custom-fonts/#from-packages 78 | 79 | fonts: 80 | - family: Bungee 81 | fonts: 82 | - asset: assets/fonts/Bungee-Regular.ttf 83 | - family: Bungee2 84 | fonts: 85 | - asset: assets/fonts/BungeeInline-Regular.ttf 86 | - family: Bungee3 87 | fonts: 88 | - asset: assets/fonts/BungeeShade-Regular.ttf 89 | - family: Heebo 90 | fonts: 91 | - asset: assets/fonts/Heebo-Regular.ttf 92 | - family: Roboto 93 | fonts: 94 | - asset: assets/fonts/Roboto-Regular.ttf 95 | - family: Audiowide 96 | fonts: 97 | - asset: assets/fonts/Audiowide-Regular.ttf -------------------------------------------------------------------------------- /ruber/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 33 | 34 | 40 | 41 | 42 | 43 | 44 | 45 | 56 | 58 | 64 | 65 | 66 | 67 | 68 | 69 | 75 | 77 | 83 | 84 | 85 | 86 | 88 | 89 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /server/src/main/java/com/rowan/ruber/model/Message.java: -------------------------------------------------------------------------------- 1 | package com.rowan.ruber.model; 2 | 3 | import java.io.Serializable; 4 | import javax.persistence.Column; 5 | import javax.persistence.Entity; 6 | import javax.persistence.GeneratedValue; 7 | import javax.persistence.GenerationType; 8 | import javax.persistence.Id; 9 | import javax.persistence.JoinColumn; 10 | import javax.persistence.ManyToOne; 11 | import javax.persistence.Table; 12 | 13 | import com.fasterxml.jackson.annotation.JsonBackReference; 14 | 15 | //import java.sql.Date; 16 | import java.util.Date; 17 | 18 | 19 | 20 | /** Class to set up the JPA Entity for the Message table in the DB. */ 21 | @Entity 22 | @Table(name="message") 23 | public class Message implements Serializable, Comparable { 24 | @Id 25 | @Column(name="MessageID") 26 | @GeneratedValue(strategy=GenerationType.IDENTITY) //Identity strategy for MySQL is auto increment 27 | private int id; 28 | 29 | @ManyToOne 30 | @JsonBackReference 31 | @JoinColumn(name = "ChatroomID") 32 | private Chatroom chatroom; 33 | 34 | @Column(name="senderID") 35 | private int senderID; 36 | 37 | @Column(name="text") 38 | private String text; 39 | 40 | @Column(name="timeSent") 41 | private Date timeSent; 42 | 43 | /** 44 | * Default constructor for JPA. 45 | * It should not be used directly as no values will be initialized. 46 | */ 47 | public Message(){} 48 | 49 | public Message(Chatroom chatroom, int senderID, String text, Date timeSent){ 50 | this.chatroom = chatroom; 51 | this.senderID = senderID; 52 | this.text = text; 53 | this.timeSent = timeSent; // SQL date or util date? 54 | } 55 | 56 | 57 | /** 58 | * Get the message id. 59 | * @return the id 60 | */ 61 | public int getId() { 62 | return id; 63 | } 64 | 65 | /** 66 | * Get the chatroom. 67 | * @return the chatroom 68 | */ 69 | public Chatroom getChatroom() { 70 | return chatroom; 71 | } 72 | 73 | /** 74 | * Get the sender. 75 | * @return a profile 76 | */ 77 | public int getSenderID() { 78 | return senderID; 79 | } 80 | 81 | /** 82 | * Get the message text. Limit of 200 characters. 83 | * @return the text 84 | */ 85 | public String getText() { 86 | return text; 87 | } 88 | 89 | /** 90 | * Get the formatted date and time this message was sent. 91 | * Avoid using SimpleDateFormat as it is not thread-safe. 92 | * @return the timeSent as a formatted String. 93 | */ 94 | public String getTimeSent() { 95 | return String.format("%1$TD %1$TT", timeSent); 96 | } 97 | 98 | /** 99 | * Set the message id 100 | * @param id the id to set 101 | */ 102 | public void setId(int id) { 103 | this.id = id; 104 | } 105 | 106 | /** 107 | * Set the chatroom. 108 | * @param chatroom the chatroom to set 109 | */ 110 | public void setChatroom(Chatroom chatroom) { 111 | this.chatroom = chatroom; 112 | } 113 | 114 | /** 115 | * Set the sender for this message. 116 | * @param sender the sender's profile 117 | */ 118 | public void setSender(int senderID) { 119 | this.senderID = senderID; 120 | } 121 | 122 | /** 123 | * Set the text for this message. 124 | * @param text the text to set 125 | */ 126 | public void setText(String text) { 127 | this.text = text; 128 | } 129 | 130 | /** 131 | * Set the date and time for this message. 132 | * @param timeSent the timeSent to set 133 | */ 134 | public void setTimeSent(Date timeSent) { 135 | this.timeSent = timeSent; 136 | } 137 | 138 | @Override 139 | public int compareTo(Message o) { 140 | return o.timeSent.compareTo(timeSent); 141 | } 142 | } -------------------------------------------------------------------------------- /server/src/main/java/com/rowan/ruber/model/Chatroom.java: -------------------------------------------------------------------------------- 1 | package com.rowan.ruber.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonBackReference; 4 | import com.fasterxml.jackson.annotation.JsonManagedReference; 5 | 6 | import javax.persistence.*; 7 | import java.io.Serializable; 8 | import java.util.*; 9 | 10 | @Entity 11 | @Table(name="chatroom") 12 | public class Chatroom implements Serializable{ 13 | @Id 14 | @Column(name="ChatroomID") 15 | @GeneratedValue(strategy=GenerationType.IDENTITY) //Identity strategy for MySQL is auto increment 16 | private int chatRoomId; 17 | 18 | @Column(name="CreatedDate") 19 | private Date createdDate; 20 | 21 | @OneToOne 22 | @JoinColumn(name="LastMessageID") 23 | private Message lastMessage; 24 | 25 | @JsonBackReference 26 | @ManyToMany(mappedBy="chatrooms") 27 | private List profiles = new ArrayList(); 28 | 29 | @JsonManagedReference 30 | @OneToMany(mappedBy = "chatroom", cascade=CascadeType.REMOVE) 31 | @OrderBy("timeSent asc ") 32 | private List messages = new ArrayList(); 33 | 34 | @Transient 35 | private HashMap emails = new HashMap(); // use this instead of profiles to stop infinite recursion 36 | 37 | @Transient 38 | private HashMap profileIDs = new HashMap(); 39 | 40 | @Transient 41 | private HashMap profileNames = new HashMap(); 42 | 43 | /** 44 | * Default constructor for JPA. 45 | * It should not be used directly as no values will be initialized. 46 | */ 47 | public Chatroom(){ 48 | } 49 | 50 | /** 51 | * When chat room is first created, there can't be a message sent yet. 52 | * A message has to belong to a chatroom, so lastMessage is initially null. 53 | * 54 | * LastMessageId is nullable on database 55 | * @param createdDate 56 | */ 57 | public Chatroom(Date createdDate){ 58 | this.createdDate = createdDate; 59 | lastMessage = null; 60 | } 61 | 62 | /** 63 | * Gets the chat room id 64 | * @return the chatRoomId 65 | */ 66 | public int getChatRoomId() { 67 | return chatRoomId; 68 | } 69 | 70 | /** 71 | * Get the formatted date and time this profile was created. 72 | * Avoid using SimpleDateFormat as it is not thread-safe. 73 | * @return the createdDate as a formatted String. 74 | */ 75 | public String getCreatedDate() { 76 | return String.format("%1$TD %1$TT", createdDate); 77 | } 78 | 79 | /** 80 | * Gets the very recent message id 81 | * @return the lastMessageId 82 | */ 83 | public Message getLastMessageId() { 84 | return lastMessage; 85 | } 86 | 87 | /** 88 | * Gets the messages for this chatroom. 89 | * @return a list of messages 90 | */ 91 | public List getMessages() { 92 | Collections.sort(messages); 93 | return messages; 94 | } 95 | 96 | /** 97 | * Gets the profiles in this chatroom. 98 | * @return a list of profiles 99 | */ 100 | public List getProfiles() { 101 | return profiles; 102 | } 103 | 104 | /** 105 | * Gets the profileIDs in this chatroom. 106 | * @return a list of profileID 107 | */ 108 | public HashMap getEmails() { 109 | return emails; 110 | } 111 | 112 | public HashMap getProfileNames() { 113 | return profileNames; 114 | } 115 | 116 | public HashMap getProfileIDs() { 117 | return profileIDs; 118 | } 119 | 120 | /** 121 | * Sets the last message. 122 | */ 123 | public void setLastMessage(Message message) { 124 | lastMessage = message; 125 | } 126 | 127 | @PostLoad 128 | public void populateTransient() { 129 | for(int i = 0; i < profiles.size(); i++) { 130 | Profile p = profiles.get(i); 131 | String current = Integer.toString(i + 1); 132 | emails.put("Profile " + current, p.getEmail()); 133 | profileNames.put("Profile " + current , p.getName()); 134 | profileIDs.put("Profile " + current, p.getId()); 135 | } 136 | 137 | 138 | } 139 | 140 | 141 | 142 | 143 | } -------------------------------------------------------------------------------- /ruber/lib/ProfileModel.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | //Takes in a JSON string and converts it to a Post object 4 | Post postFromJson(String str) { 5 | final jsonData = json.decode(str); 6 | return Post.fromJson(jsonData); 7 | } 8 | 9 | //Takes in a Post object and returns a JSON String 10 | String postToJson(Post data) { 11 | final dyn = data.toJson(); 12 | return json.encode(dyn); 13 | } 14 | 15 | //Returns a list of all Posts from a JSON String 16 | List allPostsFromJson(String str) { 17 | final jsonData = json.decode(str); 18 | return new List.from(jsonData.map((x) => Post.fromJson(x))); 19 | } 20 | 21 | //Converts a List of Posts to a Json String 22 | String allPostsToJson(List data) { 23 | final dyn = new List.from(data.map((x) => x.toJson())); 24 | return json.encode(dyn); 25 | } 26 | 27 | //Class that creates a Post object 28 | class Post { 29 | int id; 30 | String name; 31 | String email; 32 | String createdDate; 33 | Address2 address; 34 | List schedules; 35 | double distanceRounded; 36 | 37 | //Class that creates a Post 38 | Post( 39 | {this.id, 40 | this.name, 41 | this.email, 42 | this.createdDate, 43 | this.address, 44 | this.schedules, 45 | this.distanceRounded}); 46 | 47 | //Converts JSON to a Post object 48 | factory Post.fromJson(Map parsedJson) { 49 | var list = parsedJson['schedules'] as List; 50 | List scheduleList = 51 | list.map((i) => Schedule2.fromJsonSchedule(i)).toList(); 52 | return Post( 53 | id: parsedJson["id"], 54 | name: parsedJson["name"], 55 | email: parsedJson["email"], 56 | createdDate: parsedJson["createdDate"], 57 | address: Address2.fromJsonAddress(parsedJson["address"]), 58 | schedules: scheduleList, 59 | distanceRounded: parsedJson["distanceRounded"], 60 | ); 61 | } 62 | 63 | //Converts the data to JSON 64 | Map toJson() => { 65 | "id": id, 66 | "name": name, 67 | "email": email, 68 | "createdDate": createdDate, 69 | "address": address, 70 | "schedules": schedules, 71 | "distanceRounded": distanceRounded 72 | }; 73 | } 74 | 75 | //Class used to parse the nested Address objects 76 | class Address2 {String streetAddress; 77 | String city; 78 | String zipCode; 79 | String state; 80 | double latitude; 81 | double longitude; 82 | 83 | Address2({ 84 | this.streetAddress, 85 | this.city, 86 | this.zipCode, 87 | this.state, 88 | this.latitude, 89 | this.longitude, 90 | }); 91 | 92 | factory Address2.fromJsonAddress(Map json) { 93 | return Address2( 94 | streetAddress: json["streetAddress"], 95 | city: json["city"], 96 | zipCode: json["zipCode"], 97 | state: json["state"], 98 | latitude: json["latitude"], 99 | longitude: json["longitude"], 100 | ); 101 | } 102 | 103 | Map toJsonAddress() => { 104 | "streetAddress": streetAddress, 105 | "city": city, 106 | "zipCode": zipCode, 107 | "state": state, 108 | "latitude": latitude, 109 | "longitude": longitude, 110 | }; 111 | } 112 | 113 | //Class used to parse the nested Schedule objects 114 | class Schedule2 { 115 | int id; 116 | int profile; 117 | String day; 118 | String goingToRangeStart; 119 | String goingToRangeEnd; 120 | String leavingRangeStart; 121 | String leavingRangeEnd; 122 | 123 | Schedule2({ 124 | this.id, 125 | this.profile, 126 | this.day, 127 | this.goingToRangeStart, 128 | this.goingToRangeEnd, 129 | this.leavingRangeStart, 130 | this.leavingRangeEnd, 131 | }); 132 | 133 | factory Schedule2.fromJsonSchedule(Map parsedJson) { 134 | return Schedule2( 135 | id: parsedJson['id'], 136 | profile: parsedJson['profile'], 137 | day: parsedJson['day'], 138 | goingToRangeStart: parsedJson['goingToRangeStart'], 139 | goingToRangeEnd: parsedJson['goingToRangeEnd'], 140 | leavingRangeStart: parsedJson['leavingRangeStart'], 141 | leavingRangeEnd: parsedJson['leavingRangeEnd'], 142 | ); 143 | } 144 | 145 | Map toJson() => { 146 | "id": id, 147 | "profile": profile, 148 | "day": day, 149 | "goingToRangeStart": goingToRangeStart, 150 | "goingToRangeEnd": goingToRangeEnd, 151 | "leavingRangeStart": leavingRangeStart, 152 | "leavingRangeEnd": leavingRangeEnd, 153 | }; 154 | } -------------------------------------------------------------------------------- /server/src/main/java/com/rowan/ruber/model/Address.java: -------------------------------------------------------------------------------- 1 | package com.rowan.ruber.model; 2 | 3 | import java.io.Serializable; 4 | 5 | import javax.persistence.Column; 6 | import javax.persistence.Entity; 7 | import javax.persistence.GeneratedValue; 8 | import javax.persistence.GenerationType; 9 | import javax.persistence.Table; 10 | import javax.persistence.Id; 11 | 12 | /** Class to set up the JPA Entity for the Address table in the DB. */ 13 | @Entity 14 | @Table(name="address") 15 | public class Address implements Serializable{ 16 | @Id 17 | @Column(name="AddressID") 18 | @GeneratedValue(strategy=GenerationType.IDENTITY) //Identity strategy for MySQL is auto increment 19 | private int id; 20 | 21 | @Column(name="StreetAddress") 22 | private String streetAddress; 23 | 24 | @Column(name="City") 25 | private String city; 26 | 27 | @Column(name="ZipCode") 28 | private String zipCode; 29 | 30 | @Column(name="State") 31 | private String state; 32 | 33 | private double latitude; 34 | 35 | private double longitude; 36 | 37 | 38 | /** Default constructor for JPA. 39 | * It should not be used directly as no values will be initialized. 40 | */ 41 | protected Address() {} 42 | 43 | /** Constructor that takes all parameters. */ 44 | public Address(String streetAddress, String city, String state, String zipCode, double latitude, double longitude) { 45 | this.streetAddress = streetAddress; 46 | this.city = city; 47 | this.state = state; 48 | this.zipCode = zipCode; 49 | this.latitude = latitude; 50 | this.longitude = longitude; 51 | } 52 | 53 | /** 54 | * Gets the AddressID. 55 | * @return the id 56 | */ 57 | public int getId() { 58 | return id; 59 | } 60 | 61 | /** 62 | * Gets the street address. 63 | * @return the streetAddress 64 | */ 65 | public String getStreetAddress() { 66 | return streetAddress; 67 | } 68 | 69 | /** 70 | * Gets the city. 71 | * @return the city 72 | */ 73 | public String getCity() { 74 | return city; 75 | } 76 | 77 | /** 78 | * Gets the state. 79 | * @return the state 80 | */ 81 | public String getState() { 82 | return state; 83 | } 84 | 85 | /** 86 | * Gets the zip code. 87 | * @return the zipCode 88 | */ 89 | public String getZipCode() { 90 | return zipCode; 91 | } 92 | 93 | /** 94 | * Gets the latitude. 95 | * @return the latitude 96 | */ 97 | public double getLatitude() { 98 | return latitude; 99 | } 100 | 101 | /** 102 | * Gets the longitude. 103 | * @return the longitude 104 | */ 105 | public double getLongitude() { 106 | return longitude; 107 | } 108 | 109 | /** 110 | * Return the String representation for an address. 111 | * @return a String for this address 112 | */ 113 | @Override 114 | public String toString() { 115 | return String.format("%s , %s , %s %s", streetAddress, city, state, zipCode); 116 | } 117 | 118 | /** 119 | * Sets the street address. Limit of 45 characters. 120 | * @param streetAddress the streetAddress to set 121 | */ 122 | public void setStreetAddress(String streetAddress) { 123 | this.streetAddress = streetAddress; 124 | } 125 | 126 | /** 127 | * Sets the city. Limit of 45 characters. 128 | * @param city the city to set 129 | */ 130 | public void setCity(String city) { 131 | this.city = city; 132 | } 133 | 134 | /** 135 | * Sets the state. Limit of 2 characters. For example, NY for New York. 136 | * @param state the state to set 137 | */ 138 | public void setState(String state) { 139 | this.state = state.toUpperCase(); 140 | } 141 | 142 | /** 143 | * Sets the zip code. Limit of 5 characters. 144 | * @param zipCode the zipCode to set 145 | */ 146 | public void setZipCode(String zipCode) { 147 | this.zipCode = zipCode; 148 | } 149 | 150 | /** 151 | * Sets the latitude. 152 | * @param latitude the latitude to set 153 | */ 154 | public void setLatitude(double latitude) { 155 | this.latitude = latitude; 156 | } 157 | 158 | /** 159 | * Sets the longitude. 160 | * @param longitude the longitude to set 161 | */ 162 | public void setLongitude(double longitude) { 163 | this.longitude = longitude; 164 | } 165 | 166 | } -------------------------------------------------------------------------------- /server/bin/mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM http://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven2 Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' 39 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 40 | 41 | @REM set %HOME% to equivalent of $HOME 42 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 43 | 44 | @REM Execute a user defined script before this one 45 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 46 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 47 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 48 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 49 | :skipRcPre 50 | 51 | @setlocal 52 | 53 | set ERROR_CODE=0 54 | 55 | @REM To isolate internal variables from possible post scripts, we use another setlocal 56 | @setlocal 57 | 58 | @REM ==== START VALIDATION ==== 59 | if not "%JAVA_HOME%" == "" goto OkJHome 60 | 61 | echo. 62 | echo Error: JAVA_HOME not found in your environment. >&2 63 | echo Please set the JAVA_HOME variable in your environment to match the >&2 64 | echo location of your Java installation. >&2 65 | echo. 66 | goto error 67 | 68 | :OkJHome 69 | if exist "%JAVA_HOME%\bin\java.exe" goto init 70 | 71 | echo. 72 | echo Error: JAVA_HOME is set to an invalid directory. >&2 73 | echo JAVA_HOME = "%JAVA_HOME%" >&2 74 | echo Please set the JAVA_HOME variable in your environment to match the >&2 75 | echo location of your Java installation. >&2 76 | echo. 77 | goto error 78 | 79 | @REM ==== END VALIDATION ==== 80 | 81 | :init 82 | 83 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 84 | @REM Fallback to current working directory if not found. 85 | 86 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 87 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 88 | 89 | set EXEC_DIR=%CD% 90 | set WDIR=%EXEC_DIR% 91 | :findBaseDir 92 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 93 | cd .. 94 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 95 | set WDIR=%CD% 96 | goto findBaseDir 97 | 98 | :baseDirFound 99 | set MAVEN_PROJECTBASEDIR=%WDIR% 100 | cd "%EXEC_DIR%" 101 | goto endDetectBaseDir 102 | 103 | :baseDirNotFound 104 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 105 | cd "%EXEC_DIR%" 106 | 107 | :endDetectBaseDir 108 | 109 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 110 | 111 | @setlocal EnableExtensions EnableDelayedExpansion 112 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 113 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 114 | 115 | :endReadAdditionalConfig 116 | 117 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 118 | 119 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 120 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 121 | 122 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 123 | if ERRORLEVEL 1 goto error 124 | goto end 125 | 126 | :error 127 | set ERROR_CODE=1 128 | 129 | :end 130 | @endlocal & set ERROR_CODE=%ERROR_CODE% 131 | 132 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 133 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 134 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 135 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 136 | :skipRcPost 137 | 138 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 139 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 140 | 141 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 142 | 143 | exit /B %ERROR_CODE% 144 | -------------------------------------------------------------------------------- /server/mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM http://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven2 Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' 39 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 40 | 41 | @REM set %HOME% to equivalent of $HOME 42 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 43 | 44 | @REM Execute a user defined script before this one 45 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 46 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 47 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 48 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 49 | :skipRcPre 50 | 51 | @setlocal 52 | 53 | set ERROR_CODE=0 54 | 55 | @REM To isolate internal variables from possible post scripts, we use another setlocal 56 | @setlocal 57 | 58 | @REM ==== START VALIDATION ==== 59 | if not "%JAVA_HOME%" == "" goto OkJHome 60 | 61 | echo. 62 | echo Error: JAVA_HOME not found in your environment. >&2 63 | echo Please set the JAVA_HOME variable in your environment to match the >&2 64 | echo location of your Java installation. >&2 65 | echo. 66 | goto error 67 | 68 | :OkJHome 69 | if exist "%JAVA_HOME%\bin\java.exe" goto init 70 | 71 | echo. 72 | echo Error: JAVA_HOME is set to an invalid directory. >&2 73 | echo JAVA_HOME = "%JAVA_HOME%" >&2 74 | echo Please set the JAVA_HOME variable in your environment to match the >&2 75 | echo location of your Java installation. >&2 76 | echo. 77 | goto error 78 | 79 | @REM ==== END VALIDATION ==== 80 | 81 | :init 82 | 83 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 84 | @REM Fallback to current working directory if not found. 85 | 86 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 87 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 88 | 89 | set EXEC_DIR=%CD% 90 | set WDIR=%EXEC_DIR% 91 | :findBaseDir 92 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 93 | cd .. 94 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 95 | set WDIR=%CD% 96 | goto findBaseDir 97 | 98 | :baseDirFound 99 | set MAVEN_PROJECTBASEDIR=%WDIR% 100 | cd "%EXEC_DIR%" 101 | goto endDetectBaseDir 102 | 103 | :baseDirNotFound 104 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 105 | cd "%EXEC_DIR%" 106 | 107 | :endDetectBaseDir 108 | 109 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 110 | 111 | @setlocal EnableExtensions EnableDelayedExpansion 112 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 113 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 114 | 115 | :endReadAdditionalConfig 116 | 117 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 118 | 119 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 120 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 121 | 122 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 123 | if ERRORLEVEL 1 goto error 124 | goto end 125 | 126 | :error 127 | set ERROR_CODE=1 128 | 129 | :end 130 | @endlocal & set ERROR_CODE=%ERROR_CODE% 131 | 132 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 133 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 134 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 135 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 136 | :skipRcPost 137 | 138 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 139 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 140 | 141 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 142 | 143 | exit /B %ERROR_CODE% 144 | -------------------------------------------------------------------------------- /ruber/lib/ChatroomModel.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | //Takes in a JSON string and converts it to a ChatList object 4 | ChatList listFromJsonChat(String str) { 5 | final jsonData = json.decode(str); 6 | //print(jsonData); 7 | //print(ChatList.fromJson(jsonData)); 8 | return ChatList.fromJsonChat(jsonData); 9 | } 10 | 11 | //Takes in a ChatList object and returns a JSON String 12 | String listToJsonChat(ChatList data) { 13 | final dyn = data.toJson(); 14 | return json.encode(dyn); 15 | } 16 | 17 | //Takes in a Messages object and returns a JSON String 18 | String messagePostToJson(Messages data) { 19 | final dyn = data.toJson(); 20 | return json.encode(dyn); 21 | } 22 | 23 | //Takes in a Chatroom object and returns a JSON String 24 | String chatroomPostToJson(ChatRoom data) { 25 | final dyn = data.toJson(); 26 | return json.encode(dyn); 27 | } 28 | 29 | //Returns a list of all ChatList objects from a JSON String 30 | List allChatsFromJson(String str) { 31 | final jsonData = json.decode(str); 32 | return new List.from(jsonData.map((x) => ChatList.fromJsonChat(x))); 33 | } 34 | 35 | //Converts a List of ChatList objects to a JSON String 36 | String allPostsToJson(List data) { 37 | final dyn = new List.from(data.map((x) => x.toJson())); 38 | return json.encode(dyn); 39 | } 40 | 41 | //Class that shows all Chats 42 | class ChatList { 43 | List chatrooms; 44 | ChatList( 45 | {this.chatrooms}); 46 | factory ChatList.fromJsonChat(Map parsedJson) { 47 | var list = parsedJson['chatrooms'] as List; 48 | //print(list); 49 | List chatRoomList = 50 | list.map((i) => ChatRoom.fromJsonChatRoom(i)).toList(); 51 | return ChatList( 52 | chatrooms: chatRoomList, 53 | ); 54 | } 55 | Map toJson() => { 56 | "chatrooms": chatrooms, 57 | }; 58 | } 59 | 60 | //A Chatroom class that structures communication between two users 61 | class ChatRoom { 62 | int chatRoomId; 63 | String createdDate; 64 | List messages; 65 | ProfileIDs profileIDs; 66 | int profileOneID; 67 | int profileTwoID; 68 | ProfileNames profileNames; 69 | int lastMessageId; 70 | ChatRoom({ 71 | this.chatRoomId, 72 | this.createdDate, 73 | this.messages, 74 | this.profileIDs, 75 | this.profileNames, 76 | this.profileOneID, 77 | this.profileTwoID, 78 | this.lastMessageId, 79 | }); 80 | factory ChatRoom.fromJsonChatRoom(Map parsedJson) { 81 | var list = parsedJson['messages'] as List; 82 | List messageList = 83 | list.map((i) => GetMessage.fromJsonGetMessages(i)).toList(); 84 | return ChatRoom( 85 | chatRoomId: parsedJson['chatRoomId'], 86 | createdDate: parsedJson['createdDate'], 87 | messages: messageList, 88 | profileIDs: ProfileIDs.fromJsonIDs(parsedJson["profileIDs"]), 89 | profileNames: ProfileNames.fromJsonNames(parsedJson["profileNames"]), 90 | profileOneID: parsedJson['profileOneID'], 91 | profileTwoID: parsedJson['profileTwoID'], 92 | lastMessageId: parsedJson['lastMessageId'], 93 | ); 94 | } 95 | 96 | //Converts the data to JSON 97 | Map toJson() => { 98 | "chatRoomId": chatRoomId, 99 | "createdDate": createdDate, 100 | "messages": messages, 101 | "profileIDs": profileIDs, 102 | "profileNames": profileNames, 103 | "profileOneID":profileOneID, 104 | "profileTwoID":profileTwoID, 105 | "lastMessageId": lastMessageId, 106 | }; 107 | } 108 | 109 | //Class that creates a Messages object 110 | class Messages { 111 | int chatroomID; 112 | int senderID; 113 | String text; 114 | String timeSent; 115 | 116 | //Constructor for a message object 117 | Messages({ 118 | this.chatroomID, 119 | this.senderID, 120 | this.text, 121 | this.timeSent, 122 | }); 123 | 124 | //Converts the JSON to a Message 125 | factory Messages.fromJsonGetMessages(Map parsedJson) { 126 | return Messages( 127 | chatroomID: parsedJson['chatroomID'], 128 | senderID: parsedJson['senderID'], 129 | text: parsedJson['text'], 130 | timeSent: parsedJson['timeSent'], 131 | ); 132 | } 133 | //Converts the data to JSON 134 | Map toJson() => { 135 | "chatroomID": chatroomID, 136 | "senderID": senderID, 137 | "text": text, 138 | "timeSent": timeSent, 139 | }; 140 | } 141 | 142 | //Class to get the text of a chat message 143 | class GetMessage{ 144 | int id; 145 | int senderID; 146 | String text; 147 | String timeSent; 148 | 149 | //Constructs a GetMessage object that gives id, senderID, text, and timeSent 150 | GetMessage({ 151 | this.id, 152 | this.senderID, 153 | this.text, 154 | this.timeSent, 155 | }); 156 | 157 | //Converts the JSON to a GetMessage 158 | factory GetMessage.fromJsonGetMessages(Map parsedJson) { 159 | return GetMessage( 160 | id:parsedJson['id'], 161 | senderID: parsedJson['senderID'], 162 | text: parsedJson['text'], 163 | timeSent: parsedJson['timeSent'], 164 | ); 165 | } 166 | 167 | //Converts the data to JSON 168 | Map toJson() => { 169 | "id:": id, 170 | "senderID": senderID, 171 | "text": text, 172 | "timeSent": timeSent, 173 | }; 174 | } 175 | 176 | //Class that allows parsing of the profile ID's in chatroom 177 | class ProfileIDs { 178 | int profile1; 179 | int profile2; 180 | ProfileIDs({ 181 | this.profile1, 182 | this.profile2, 183 | }); 184 | factory ProfileIDs.fromJsonIDs(Map parsedJson) { 185 | return ProfileIDs( 186 | profile1: parsedJson['Profile 1'], 187 | profile2: parsedJson['Profile 2'], 188 | ); 189 | } 190 | Map toJson() => { 191 | "Profile 1": profile1, 192 | "Profile 2": profile2, 193 | }; 194 | } 195 | 196 | //Constructor for a ProfileNames object 197 | class ProfileNames { 198 | String profile1; 199 | String profile2; 200 | ProfileNames({ 201 | this.profile1, 202 | this.profile2, 203 | }); 204 | 205 | //Converts the JSON to a ProfileNames object 206 | factory ProfileNames.fromJsonNames(Map parsedJson) { 207 | return ProfileNames( 208 | profile1: parsedJson['Profile 1'], 209 | profile2: parsedJson['Profile 2'], 210 | ); 211 | } 212 | 213 | //Converts the data to JSON 214 | Map toJson() => { 215 | "Profile 1": profile1, 216 | "Profile 2": profile2, 217 | }; 218 | } -------------------------------------------------------------------------------- /server/src/main/java/com/rowan/ruber/model/Profile.java: -------------------------------------------------------------------------------- 1 | package com.rowan.ruber.model; 2 | 3 | import javax.persistence.*; 4 | import java.io.Serializable; 5 | import java.util.Date; 6 | import java.text.SimpleDateFormat; 7 | import java.util.List; 8 | import java.util.ArrayList; 9 | 10 | /** 11 | * Class to set up the JPA Entity for the Profile table in the database 12 | */ 13 | @Entity 14 | @Table(name = "profile") 15 | public class Profile implements Serializable{ 16 | @Id 17 | @GeneratedValue(strategy = GenerationType.IDENTITY) 18 | @Column(name="profileID") 19 | private int id; 20 | 21 | private String name; 22 | 23 | @Column(name="EmailAddress") 24 | private String emailAddress; 25 | 26 | // Refers to address table 27 | // ** Leaving out ON UPDATE ON DELETE for now since they are defined in MySQL - will add later if needed. 28 | @OneToOne(cascade=CascadeType.REMOVE) 29 | @JoinColumn(name="AddressID") 30 | private Address address; 31 | 32 | @Column(name="CreatedDate") 33 | private Date createdDate; 34 | 35 | @OneToMany(mappedBy="profile", cascade=CascadeType.REMOVE) 36 | private List schedules = new ArrayList(); // Maintain bi-directional 1 to Many w/ Schedule 37 | 38 | @ManyToMany 39 | @JoinTable(name = "chatroomProfile", 40 | joinColumns = { @JoinColumn(name = "ProfileID") }, 41 | inverseJoinColumns = { @JoinColumn(name = "ChatroomID") }) 42 | private List chatrooms = new ArrayList(); //Profile is the "owner" side of the relationship 43 | 44 | @Transient 45 | private double distance; 46 | @Transient 47 | private double distanceRounded; 48 | @Transient 49 | private String schedulesString; 50 | 51 | /** 52 | * Default constructor for JPA. 53 | * It should not be used directly as no values will be initialized. 54 | */ 55 | public Profile(){ 56 | 57 | } 58 | 59 | public Profile(String name, String email, Address address, Date createdDate){ 60 | this.name = name; 61 | this.emailAddress = email; 62 | this.address = address; 63 | this.createdDate = createdDate; 64 | } 65 | 66 | /** 67 | * Constructor used when matching is done. 68 | * @param name Name of the matched profile 69 | * @param email Email Address of the matched profile 70 | * @param address Address of the matched profile 71 | * @param distance Distance of the matched profile 72 | */ 73 | public Profile(String name, String email, Address address, double distance, double distanceRounded){ 74 | this.name = name; 75 | this.emailAddress = email; 76 | this.address = address; 77 | this.distance = distance; 78 | this.distanceRounded = distanceRounded; 79 | } 80 | 81 | /** 82 | * Returns the string representation for Profile. 83 | * @return the String representation for a Profile 84 | */ 85 | public String toString(){ 86 | SimpleDateFormat sdf = new SimpleDateFormat("MM-dd-yyyy"); 87 | return String.format("Name: %s %n Email: %s %n AddressID: %d %n Created Date: %s %n", 88 | name, emailAddress, address.toString(), sdf.format(createdDate)); 89 | } 90 | 91 | /** 92 | * Gets the profile id. 93 | * @return the id 94 | */ 95 | public int getId() { 96 | return id; 97 | } 98 | 99 | /** 100 | * Gets the name. 101 | * @return the name 102 | */ 103 | public String getName() { 104 | return name; 105 | } 106 | 107 | /** 108 | * Gets the email. 109 | * @return the email 110 | */ 111 | public String getEmail() { 112 | return emailAddress; 113 | } 114 | 115 | /** 116 | * Gets the address. 117 | * @return the address 118 | */ 119 | public Address getAddress() { 120 | return address; 121 | } 122 | 123 | /** 124 | * Get the formatted date and time this profile was created. 125 | * Avoid using SimpleDateFormat as it is not thread-safe. 126 | * @return the createdDate as a formatted String. 127 | */ 128 | public String getCreatedDate() { 129 | return String.format("%1$TD %1$TT", createdDate); 130 | } 131 | 132 | /** 133 | * Gets the schedules for a profile. 134 | * @return a list of schedules 135 | */ 136 | public List getSchedules() { 137 | return schedules; 138 | } 139 | 140 | /** 141 | * Gets the chatrooms that this profile is in. 142 | * @return a list of chatrooms 143 | */ 144 | public List getChatrooms() { 145 | return chatrooms; 146 | } 147 | 148 | /** 149 | * Gets the un-rounded distance to another profile. 150 | * @return the un-rounded distance. 151 | */ 152 | public double getDistance() {return distance;} 153 | 154 | /** 155 | * Gets the rounded distance to another profile. 156 | * @return the rounded distance. 157 | */ 158 | public double getDistanceRounded() {return distanceRounded;} 159 | 160 | /** 161 | * Gets a string that represents the list of schedules 162 | * @return a string that represents the list of schedules. 163 | */ 164 | public String getSchedulesString() {return schedulesString;} 165 | 166 | /** 167 | * Sets the address. 168 | * @param address the address object to set to 169 | */ 170 | public void setAddress(Address address) { 171 | this.address = address; 172 | } 173 | 174 | /** 175 | * Sets the email. Limit of 45 characters. 176 | * @param email the email to set 177 | */ 178 | public void setEmail(String email) { 179 | this.emailAddress = email; 180 | } 181 | 182 | /** 183 | * Sets the name. Limit of 90 characters. 184 | * @param name the name to set 185 | */ 186 | public void setName(String name) { 187 | this.name = name; 188 | } 189 | 190 | /** 191 | * Sets the schedule. Should only be used for displaying needs. 192 | * Note that this method cannot be used to commit schedule changes to the database - not the owner side of the relationship 193 | * between schedule and profile. 194 | * 195 | * @param schedules the schedules to set 196 | */ 197 | public void setSchedules(List schedules) { 198 | this.schedules = schedules; 199 | } 200 | 201 | /** 202 | * Sets the string that represents a list of schedules. 203 | * @param string represents the list of schedules. 204 | */ 205 | public void setSchedulesString(String string) {this.schedulesString = string;} 206 | } 207 | -------------------------------------------------------------------------------- /ruber/lib/Main.dart: -------------------------------------------------------------------------------- 1 | /// Main.dart 2 | /// 3 | /// Purpose: 4 | /// The purpose of this file is to act as the main starting point 5 | /// of the app. It describes the Welcome screen which goes 6 | /// to the Google OAuth screen. This also includes the main 7 | /// menu screen which is the starting point of the app once the user 8 | /// is created. 9 | 10 | 11 | /// Imports 12 | import 'package:flutter/foundation.dart'; 13 | import 'package:flutter/material.dart'; 14 | 15 | import 'AppDrawer.dart'; 16 | import 'AuthScreen.dart'; 17 | import 'ChatRoomScreen.dart'; 18 | import 'RideScreen.dart'; 19 | import 'editschedule.dart'; 20 | import 'profile.dart'; 21 | 22 | var api_key = "AIzaSyDrHKl8IxB4cGXIoELXQOzzZwiH1xtsRf4"; 23 | 24 | void main() => runApp(new RUber()); 25 | 26 | class RUber extends StatelessWidget { 27 | @override 28 | Widget build(BuildContext context) { 29 | return MaterialApp( 30 | title: 'Ryde', 31 | debugShowCheckedModeBanner: false, 32 | home: WelcomeScreen()); 33 | } 34 | } 35 | 36 | /// ==================== WELCOME SCREEN ====================== // 37 | 38 | class WelcomeScreen extends StatelessWidget { 39 | @override 40 | Widget build(BuildContext context) { 41 | return Scaffold( 42 | appBar: AppBar( 43 | title: Text('Welcome to Ryde'), 44 | centerTitle: true, 45 | automaticallyImplyLeading: false, 46 | ), 47 | body: Center( 48 | child: Column( 49 | children: [ 50 | Container( 51 | margin: EdgeInsets.only(top: 15.0, bottom: 15.0), 52 | child: Text( 53 | 'Ryde', 54 | style: TextStyle( 55 | fontWeight: FontWeight.bold, 56 | color: Colors.orange, 57 | fontSize: 80.0, 58 | fontFamily: "Audiowide"), 59 | ), 60 | ), 61 | Image.network( 62 | 'https://www.tlcrentalmarketplace.com/wp-content/uploads/2018/03/rideshare.png', 63 | height: 150, 64 | ), 65 | Container( 66 | margin: EdgeInsets.only( 67 | top: 40.0, left: 15.0, right: 15.0, bottom: 15.0), 68 | child: Text( 69 | 'Exclusively for Rowan University students\n\n Commute with other students near you\n\n Match based on class schedule and distance\n\n Save gas and the planet!', 70 | style: TextStyle( 71 | color: Colors.black, 72 | fontSize: 18.0, 73 | fontFamily: "", 74 | ), 75 | textAlign: TextAlign.center, 76 | ), 77 | ), 78 | MaterialButton( 79 | child: Text( 80 | "Start", 81 | style: TextStyle(fontSize: 20), 82 | ), 83 | textColor: Colors.white, 84 | color: Colors.blue, 85 | minWidth: 100.0, 86 | height: 70.0, 87 | onPressed: () { 88 | Navigator.push(context, 89 | MaterialPageRoute(builder: (context) => MyAuthScreen())); 90 | }, 91 | ), 92 | ], 93 | ), 94 | )); 95 | } 96 | } 97 | 98 | /// =========================== END WELCOME SCREEN ====================== // 99 | 100 | class MainScreen extends StatelessWidget { 101 | final GlobalKey _scaffoldKey = new GlobalKey(); 102 | 103 | final String title; 104 | 105 | MainScreen({Key key, this.title}) : super(key: key); 106 | 107 | @override 108 | Widget build(BuildContext context) { 109 | return WillPopScope( 110 | onWillPop: () async => false, 111 | child: Scaffold( 112 | appBar: AppBar( 113 | title: Text('Ryde', 114 | style: TextStyle( 115 | fontSize: 30, 116 | fontFamily: "Audiowide", 117 | color: Colors.white)), 118 | centerTitle: true, 119 | leading: IconButton( 120 | icon: new Image.network( 121 | 'https://www.tlcrentalmarketplace.com/wp-content/uploads/2018/03/rideshare.png'), 122 | onPressed: () => _scaffoldKey.currentState.openDrawer()), 123 | ), 124 | drawer: launchAppDrawer(context), 125 | key: _scaffoldKey, 126 | body: Center( 127 | child: Column(children: [ 128 | Image.network( 129 | 'https://www.tlcrentalmarketplace.com/wp-content/uploads/2018/03/rideshare.png', 130 | height: 150, 131 | ), 132 | ListTile( 133 | leading: Icon(Icons.directions_car), 134 | title: Text('New Ryde'), 135 | contentPadding: new EdgeInsets.only(left: 100.0, top: 30.0), 136 | onTap: () { 137 | Navigator.push( 138 | context, 139 | MaterialPageRoute( 140 | builder: (context) => launchRideScreen())); 141 | }), 142 | ListTile( 143 | leading: Icon(Icons.message), 144 | title: Text('Messages'), 145 | contentPadding: new EdgeInsets.only(left: 100.0), 146 | onTap: () { 147 | Navigator.push( 148 | context, 149 | MaterialPageRoute(builder: (context) => ChatRoomScreen()), 150 | ); 151 | }, 152 | ), 153 | ListTile( 154 | leading: Icon(Icons.account_box), 155 | title: Text('Profile'), 156 | contentPadding: new EdgeInsets.only(left: 100.0), 157 | onTap: () { 158 | Navigator.push( 159 | context, 160 | MaterialPageRoute(builder: (context) => ProfileScreen()), 161 | ); 162 | }, 163 | ), 164 | ListTile( 165 | leading: Icon(Icons.schedule), 166 | title: Text('Schedule'), 167 | contentPadding: new EdgeInsets.only(left: 100.0), 168 | onTap: () { 169 | Navigator.push( 170 | context, 171 | MaterialPageRoute( 172 | builder: (context) => ScheduleForm())); 173 | }, 174 | ) 175 | ]), 176 | ))); 177 | } 178 | } 179 | -------------------------------------------------------------------------------- /server/src/main/java/com/rowan/ruber/Search.java: -------------------------------------------------------------------------------- 1 | package com.rowan.ruber; 2 | 3 | import com.rowan.ruber.model.*; 4 | import com.rowan.ruber.repository.*; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.stereotype.Component; 7 | import org.springframework.jdbc.core.JdbcTemplate; 8 | import org.springframework.jdbc.core.RowMapper; 9 | import org.springframework.jdbc.core.ResultSetExtractor; 10 | import java.sql.ResultSet; 11 | 12 | import java.sql.SQLException; 13 | import java.util.List; 14 | import java.util.Iterator; 15 | 16 | @Component 17 | public class Search{ 18 | 19 | @Autowired 20 | JdbcTemplate jdbcTemplate; 21 | 22 | /** 23 | * Gets a list of profiles that match with the user 24 | * 25 | * @param repo the repository that stores the profiles 26 | * @param profileID id of the user 27 | * @param radius search radius in miles 28 | * @return a list of profiles that match with the user based on distance and schedule 29 | */ 30 | public List getMatches(ProfileRepository repo, int profileID, int radius) { 31 | // Gets the profile object from the repository 32 | Profile profile = repo.findById(profileID).get(); 33 | List matchedProfiles = getMatchesByDistance(profileID, profile.getAddress().getLatitude(), profile.getAddress().getLongitude(), radius); 34 | Iterator profileIterator = matchedProfiles.iterator(); 35 | while(profileIterator.hasNext()) { 36 | Profile checkProfile = profileIterator.next(); 37 | boolean foundMatchedProfile = false; 38 | String matchedSchedulesString = ""; 39 | Iterator scheduleIterator = checkProfile.getSchedules().iterator(); 40 | // Checks though each schedule and looks for a match 41 | while(scheduleIterator.hasNext()) 42 | { 43 | Schedule checkSchedule = scheduleIterator.next(); 44 | boolean foundMatchedSchedule = false; 45 | for (Schedule s: profile.getSchedules()) { 46 | if(checkSchedule.updateWithMatchedTime(s)) 47 | { 48 | foundMatchedSchedule = true; 49 | foundMatchedProfile = true; 50 | } 51 | } 52 | if(foundMatchedSchedule) 53 | matchedSchedulesString += Day.toCharacter(checkSchedule.getDay()) + " "; 54 | else 55 | scheduleIterator.remove(); 56 | } 57 | if(foundMatchedProfile) 58 | checkProfile.setSchedulesString(matchedSchedulesString.trim()); 59 | else 60 | profileIterator.remove(); //profile is removed from the list if no matches are found with the schedules 61 | 62 | } 63 | return matchedProfiles; 64 | } 65 | 66 | /** 67 | * Gets a list of profiles that are within a specified radius of the user 68 | * 69 | * @param profileID id of the user 70 | * @param lat latitude that corresponds to the user's address 71 | * @param lng longitude that corresponds to the user's address 72 | * @param radius search radius in miles 73 | * @return a list of profiles that match with the user based on distance. 74 | */ 75 | private List getMatchesByDistance(int profileID, double lat, double lng, double radius){ 76 | List matchedProfiles = jdbcTemplate.query( 77 | "SELECT *, ( 3959* ACOS( COS( RADIANS(?) ) * COS( RADIANS( Latitude ) ) * COS( RADIANS( Longitude ) - RADIANS(?) ) + SIN( RADIANS(?) ) * SIN( RADIANS( Latitude ) ) ) ) AS Distance FROM address JOIN profile USING (AddressID) WHERE ProfileID <> ? HAVING Distance < ? ORDER BY Distance;", 78 | new Object[] {lat, lng, lat, profileID, radius}, 79 | new ProfileRowMapper()); 80 | for (Profile profile : matchedProfiles ) { 81 | List schedules = jdbcTemplate.query( 82 | "SELECT * FROM schedule JOIN profile USING (ProfileID) WHERE EmailAddress = ?;", 83 | new Object[]{profile.getEmail()}, 84 | new ScheduleRowMapper()); 85 | schedules.sort(new SortByDay()); 86 | for (Schedule schedule : schedules) 87 | { 88 | schedule.setProfile(profile); 89 | } 90 | profile.setSchedules(schedules); 91 | } 92 | return matchedProfiles; 93 | } 94 | 95 | /** 96 | * Truncates a double to the nearest hundredth 97 | * @param d double to be truncated 98 | * @return truncated double 99 | */ 100 | private double Round(double d) 101 | { 102 | int i = (int)(d * 100); 103 | return (i + 0.0)/100; 104 | } 105 | 106 | public class ProfileResultSetExtractor implements ResultSetExtractor { 107 | @Override 108 | public Object extractData(ResultSet rs) throws SQLException { 109 | return new Profile(rs.getString("Name"), 110 | rs.getString("EmailAddress"), 111 | new Address(rs.getString("StreetAddress"), 112 | rs.getString("City"), 113 | rs.getString("State"), 114 | rs.getString("ZipCode"), 115 | rs.getDouble("Latitude"), 116 | rs.getDouble("Longitude") 117 | ), 118 | rs.getDouble("Distance"), 119 | Round(rs.getDouble("Distance")) 120 | ); 121 | } 122 | } 123 | 124 | public class ProfileRowMapper implements RowMapper{ 125 | @Override 126 | public Object mapRow(ResultSet rs, int line) throws SQLException { 127 | ProfileResultSetExtractor extractor = new ProfileResultSetExtractor(); 128 | return extractor.extractData(rs); 129 | } 130 | } 131 | 132 | public class ScheduleResultSetExtractor implements ResultSetExtractor{ 133 | @Override 134 | public Object extractData(ResultSet rs) throws SQLException { 135 | return new Schedule(Day.valueOf(rs.getString("Day")), 136 | rs.getTime("GoingToRangeStart").toLocalTime(), 137 | rs.getTime("GoingToRangeEnd").toLocalTime(), 138 | rs.getTime("LeavingRangeStart").toLocalTime(), 139 | rs.getTime("LeavingRangeEnd").toLocalTime() 140 | ); 141 | } 142 | } 143 | 144 | public class ScheduleRowMapper implements RowMapper{ 145 | @Override 146 | public Object mapRow(ResultSet rs, int line) throws SQLException { 147 | ScheduleResultSetExtractor extractor = new ScheduleResultSetExtractor(); 148 | return extractor.extractData(rs); 149 | } 150 | } 151 | } -------------------------------------------------------------------------------- /server/mvnw: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ---------------------------------------------------------------------------- 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | # ---------------------------------------------------------------------------- 20 | 21 | # ---------------------------------------------------------------------------- 22 | # Maven2 Start Up Batch script 23 | # 24 | # Required ENV vars: 25 | # ------------------ 26 | # JAVA_HOME - location of a JDK home dir 27 | # 28 | # Optional ENV vars 29 | # ----------------- 30 | # M2_HOME - location of maven2's installed home dir 31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven 32 | # e.g. to debug Maven itself, use 33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files 35 | # ---------------------------------------------------------------------------- 36 | 37 | if [ -z "$MAVEN_SKIP_RC" ] ; then 38 | 39 | if [ -f /etc/mavenrc ] ; then 40 | . /etc/mavenrc 41 | fi 42 | 43 | if [ -f "$HOME/.mavenrc" ] ; then 44 | . "$HOME/.mavenrc" 45 | fi 46 | 47 | fi 48 | 49 | # OS specific support. $var _must_ be set to either true or false. 50 | cygwin=false; 51 | darwin=false; 52 | mingw=false 53 | case "`uname`" in 54 | CYGWIN*) cygwin=true ;; 55 | MINGW*) mingw=true;; 56 | Darwin*) darwin=true 57 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home 58 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html 59 | if [ -z "$JAVA_HOME" ]; then 60 | if [ -x "/usr/libexec/java_home" ]; then 61 | export JAVA_HOME="`/usr/libexec/java_home`" 62 | else 63 | export JAVA_HOME="/Library/Java/Home" 64 | fi 65 | fi 66 | ;; 67 | esac 68 | 69 | if [ -z "$JAVA_HOME" ] ; then 70 | if [ -r /etc/gentoo-release ] ; then 71 | JAVA_HOME=`java-config --jre-home` 72 | fi 73 | fi 74 | 75 | if [ -z "$M2_HOME" ] ; then 76 | ## resolve links - $0 may be a link to maven's home 77 | PRG="$0" 78 | 79 | # need this for relative symlinks 80 | while [ -h "$PRG" ] ; do 81 | ls=`ls -ld "$PRG"` 82 | link=`expr "$ls" : '.*-> \(.*\)$'` 83 | if expr "$link" : '/.*' > /dev/null; then 84 | PRG="$link" 85 | else 86 | PRG="`dirname "$PRG"`/$link" 87 | fi 88 | done 89 | 90 | saveddir=`pwd` 91 | 92 | M2_HOME=`dirname "$PRG"`/.. 93 | 94 | # make it fully qualified 95 | M2_HOME=`cd "$M2_HOME" && pwd` 96 | 97 | cd "$saveddir" 98 | # echo Using m2 at $M2_HOME 99 | fi 100 | 101 | # For Cygwin, ensure paths are in UNIX format before anything is touched 102 | if $cygwin ; then 103 | [ -n "$M2_HOME" ] && 104 | M2_HOME=`cygpath --unix "$M2_HOME"` 105 | [ -n "$JAVA_HOME" ] && 106 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 107 | [ -n "$CLASSPATH" ] && 108 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"` 109 | fi 110 | 111 | # For Migwn, ensure paths are in UNIX format before anything is touched 112 | if $mingw ; then 113 | [ -n "$M2_HOME" ] && 114 | M2_HOME="`(cd "$M2_HOME"; pwd)`" 115 | [ -n "$JAVA_HOME" ] && 116 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" 117 | # TODO classpath? 118 | fi 119 | 120 | if [ -z "$JAVA_HOME" ]; then 121 | javaExecutable="`which javac`" 122 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then 123 | # readlink(1) is not available as standard on Solaris 10. 124 | readLink=`which readlink` 125 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then 126 | if $darwin ; then 127 | javaHome="`dirname \"$javaExecutable\"`" 128 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" 129 | else 130 | javaExecutable="`readlink -f \"$javaExecutable\"`" 131 | fi 132 | javaHome="`dirname \"$javaExecutable\"`" 133 | javaHome=`expr "$javaHome" : '\(.*\)/bin'` 134 | JAVA_HOME="$javaHome" 135 | export JAVA_HOME 136 | fi 137 | fi 138 | fi 139 | 140 | if [ -z "$JAVACMD" ] ; then 141 | if [ -n "$JAVA_HOME" ] ; then 142 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 143 | # IBM's JDK on AIX uses strange locations for the executables 144 | JAVACMD="$JAVA_HOME/jre/sh/java" 145 | else 146 | JAVACMD="$JAVA_HOME/bin/java" 147 | fi 148 | else 149 | JAVACMD="`which java`" 150 | fi 151 | fi 152 | 153 | if [ ! -x "$JAVACMD" ] ; then 154 | echo "Error: JAVA_HOME is not defined correctly." >&2 155 | echo " We cannot execute $JAVACMD" >&2 156 | exit 1 157 | fi 158 | 159 | if [ -z "$JAVA_HOME" ] ; then 160 | echo "Warning: JAVA_HOME environment variable is not set." 161 | fi 162 | 163 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher 164 | 165 | # traverses directory structure from process work directory to filesystem root 166 | # first directory with .mvn subdirectory is considered project base directory 167 | find_maven_basedir() { 168 | 169 | if [ -z "$1" ] 170 | then 171 | echo "Path not specified to find_maven_basedir" 172 | return 1 173 | fi 174 | 175 | basedir="$1" 176 | wdir="$1" 177 | while [ "$wdir" != '/' ] ; do 178 | if [ -d "$wdir"/.mvn ] ; then 179 | basedir=$wdir 180 | break 181 | fi 182 | # workaround for JBEAP-8937 (on Solaris 10/Sparc) 183 | if [ -d "${wdir}" ]; then 184 | wdir=`cd "$wdir/.."; pwd` 185 | fi 186 | # end of workaround 187 | done 188 | echo "${basedir}" 189 | } 190 | 191 | # concatenates all lines of a file 192 | concat_lines() { 193 | if [ -f "$1" ]; then 194 | echo "$(tr -s '\n' ' ' < "$1")" 195 | fi 196 | } 197 | 198 | BASE_DIR=`find_maven_basedir "$(pwd)"` 199 | if [ -z "$BASE_DIR" ]; then 200 | exit 1; 201 | fi 202 | 203 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} 204 | echo $MAVEN_PROJECTBASEDIR 205 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 206 | 207 | # For Cygwin, switch paths to Windows format before running java 208 | if $cygwin; then 209 | [ -n "$M2_HOME" ] && 210 | M2_HOME=`cygpath --path --windows "$M2_HOME"` 211 | [ -n "$JAVA_HOME" ] && 212 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` 213 | [ -n "$CLASSPATH" ] && 214 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"` 215 | [ -n "$MAVEN_PROJECTBASEDIR" ] && 216 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` 217 | fi 218 | 219 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 220 | 221 | exec "$JAVACMD" \ 222 | $MAVEN_OPTS \ 223 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ 224 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ 225 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" 226 | -------------------------------------------------------------------------------- /server/bin/mvnw: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ---------------------------------------------------------------------------- 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | # ---------------------------------------------------------------------------- 20 | 21 | # ---------------------------------------------------------------------------- 22 | # Maven2 Start Up Batch script 23 | # 24 | # Required ENV vars: 25 | # ------------------ 26 | # JAVA_HOME - location of a JDK home dir 27 | # 28 | # Optional ENV vars 29 | # ----------------- 30 | # M2_HOME - location of maven2's installed home dir 31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven 32 | # e.g. to debug Maven itself, use 33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files 35 | # ---------------------------------------------------------------------------- 36 | 37 | if [ -z "$MAVEN_SKIP_RC" ] ; then 38 | 39 | if [ -f /etc/mavenrc ] ; then 40 | . /etc/mavenrc 41 | fi 42 | 43 | if [ -f "$HOME/.mavenrc" ] ; then 44 | . "$HOME/.mavenrc" 45 | fi 46 | 47 | fi 48 | 49 | # OS specific support. $var _must_ be set to either true or false. 50 | cygwin=false; 51 | darwin=false; 52 | mingw=false 53 | case "`uname`" in 54 | CYGWIN*) cygwin=true ;; 55 | MINGW*) mingw=true;; 56 | Darwin*) darwin=true 57 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home 58 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html 59 | if [ -z "$JAVA_HOME" ]; then 60 | if [ -x "/usr/libexec/java_home" ]; then 61 | export JAVA_HOME="`/usr/libexec/java_home`" 62 | else 63 | export JAVA_HOME="/Library/Java/Home" 64 | fi 65 | fi 66 | ;; 67 | esac 68 | 69 | if [ -z "$JAVA_HOME" ] ; then 70 | if [ -r /etc/gentoo-release ] ; then 71 | JAVA_HOME=`java-config --jre-home` 72 | fi 73 | fi 74 | 75 | if [ -z "$M2_HOME" ] ; then 76 | ## resolve links - $0 may be a link to maven's home 77 | PRG="$0" 78 | 79 | # need this for relative symlinks 80 | while [ -h "$PRG" ] ; do 81 | ls=`ls -ld "$PRG"` 82 | link=`expr "$ls" : '.*-> \(.*\)$'` 83 | if expr "$link" : '/.*' > /dev/null; then 84 | PRG="$link" 85 | else 86 | PRG="`dirname "$PRG"`/$link" 87 | fi 88 | done 89 | 90 | saveddir=`pwd` 91 | 92 | M2_HOME=`dirname "$PRG"`/.. 93 | 94 | # make it fully qualified 95 | M2_HOME=`cd "$M2_HOME" && pwd` 96 | 97 | cd "$saveddir" 98 | # echo Using m2 at $M2_HOME 99 | fi 100 | 101 | # For Cygwin, ensure paths are in UNIX format before anything is touched 102 | if $cygwin ; then 103 | [ -n "$M2_HOME" ] && 104 | M2_HOME=`cygpath --unix "$M2_HOME"` 105 | [ -n "$JAVA_HOME" ] && 106 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 107 | [ -n "$CLASSPATH" ] && 108 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"` 109 | fi 110 | 111 | # For Migwn, ensure paths are in UNIX format before anything is touched 112 | if $mingw ; then 113 | [ -n "$M2_HOME" ] && 114 | M2_HOME="`(cd "$M2_HOME"; pwd)`" 115 | [ -n "$JAVA_HOME" ] && 116 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" 117 | # TODO classpath? 118 | fi 119 | 120 | if [ -z "$JAVA_HOME" ]; then 121 | javaExecutable="`which javac`" 122 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then 123 | # readlink(1) is not available as standard on Solaris 10. 124 | readLink=`which readlink` 125 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then 126 | if $darwin ; then 127 | javaHome="`dirname \"$javaExecutable\"`" 128 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" 129 | else 130 | javaExecutable="`readlink -f \"$javaExecutable\"`" 131 | fi 132 | javaHome="`dirname \"$javaExecutable\"`" 133 | javaHome=`expr "$javaHome" : '\(.*\)/bin'` 134 | JAVA_HOME="$javaHome" 135 | export JAVA_HOME 136 | fi 137 | fi 138 | fi 139 | 140 | if [ -z "$JAVACMD" ] ; then 141 | if [ -n "$JAVA_HOME" ] ; then 142 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 143 | # IBM's JDK on AIX uses strange locations for the executables 144 | JAVACMD="$JAVA_HOME/jre/sh/java" 145 | else 146 | JAVACMD="$JAVA_HOME/bin/java" 147 | fi 148 | else 149 | JAVACMD="`which java`" 150 | fi 151 | fi 152 | 153 | if [ ! -x "$JAVACMD" ] ; then 154 | echo "Error: JAVA_HOME is not defined correctly." >&2 155 | echo " We cannot execute $JAVACMD" >&2 156 | exit 1 157 | fi 158 | 159 | if [ -z "$JAVA_HOME" ] ; then 160 | echo "Warning: JAVA_HOME environment variable is not set." 161 | fi 162 | 163 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher 164 | 165 | # traverses directory structure from process work directory to filesystem root 166 | # first directory with .mvn subdirectory is considered project base directory 167 | find_maven_basedir() { 168 | 169 | if [ -z "$1" ] 170 | then 171 | echo "Path not specified to find_maven_basedir" 172 | return 1 173 | fi 174 | 175 | basedir="$1" 176 | wdir="$1" 177 | while [ "$wdir" != '/' ] ; do 178 | if [ -d "$wdir"/.mvn ] ; then 179 | basedir=$wdir 180 | break 181 | fi 182 | # workaround for JBEAP-8937 (on Solaris 10/Sparc) 183 | if [ -d "${wdir}" ]; then 184 | wdir=`cd "$wdir/.."; pwd` 185 | fi 186 | # end of workaround 187 | done 188 | echo "${basedir}" 189 | } 190 | 191 | # concatenates all lines of a file 192 | concat_lines() { 193 | if [ -f "$1" ]; then 194 | echo "$(tr -s '\n' ' ' < "$1")" 195 | fi 196 | } 197 | 198 | BASE_DIR=`find_maven_basedir "$(pwd)"` 199 | if [ -z "$BASE_DIR" ]; then 200 | exit 1; 201 | fi 202 | 203 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} 204 | echo $MAVEN_PROJECTBASEDIR 205 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 206 | 207 | # For Cygwin, switch paths to Windows format before running java 208 | if $cygwin; then 209 | [ -n "$M2_HOME" ] && 210 | M2_HOME=`cygpath --path --windows "$M2_HOME"` 211 | [ -n "$JAVA_HOME" ] && 212 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` 213 | [ -n "$CLASSPATH" ] && 214 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"` 215 | [ -n "$MAVEN_PROJECTBASEDIR" ] && 216 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` 217 | fi 218 | 219 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 220 | 221 | exec "$JAVACMD" \ 222 | $MAVEN_OPTS \ 223 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ 224 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ 225 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" 226 | -------------------------------------------------------------------------------- /server/src/main/java/com/rowan/ruber/model/Schedule.java: -------------------------------------------------------------------------------- 1 | package com.rowan.ruber.model; 2 | 3 | import java.io.Serializable; 4 | import java.time.LocalTime; 5 | import java.util.Comparator; 6 | import javax.persistence.Column; 7 | import javax.persistence.Entity; 8 | import javax.persistence.EnumType; 9 | import javax.persistence.Enumerated; 10 | import javax.persistence.GeneratedValue; 11 | import javax.persistence.GenerationType; 12 | import javax.persistence.Id; 13 | import javax.persistence.JoinColumn; 14 | import javax.persistence.ManyToOne; 15 | import javax.persistence.Table; 16 | 17 | import com.fasterxml.jackson.annotation.JsonBackReference; 18 | 19 | /** 20 | * Class to set up the JPA Entity for the Schedule table in the database. 21 | * Each schedule is represented by a day of the week and time ranges for going and leaving. 22 | */ 23 | @Entity 24 | @Table(name="schedule") 25 | public class Schedule implements Serializable { 26 | @Id 27 | @GeneratedValue(strategy = GenerationType.IDENTITY) 28 | @Column(name = "scheduleID") 29 | private int id; 30 | 31 | @ManyToOne 32 | @JsonBackReference 33 | @JoinColumn(name = "ProfileID") 34 | private Profile profile; 35 | 36 | @Enumerated(EnumType.STRING) 37 | @Column(name = "Day") 38 | private Day day; 39 | 40 | @Column(name = "GoingToRangeStart") 41 | private LocalTime goingToStart; 42 | 43 | @Column(name = "GoingToRangeEnd") 44 | private LocalTime goingToEnd; 45 | 46 | @Column(name = "LeavingRangeStart") 47 | private LocalTime leavingStart; 48 | 49 | @Column(name = "LeavingRangeEnd") 50 | private LocalTime leavingEnd; 51 | 52 | /** 53 | * Default constructor for JPA. 54 | * It should not be used directly as no values will be initialized. 55 | */ 56 | public Schedule() { 57 | 58 | } 59 | 60 | /** 61 | * Constructor that takes all parameters. 62 | * 63 | * @param profile the profile for this schedule 64 | * @param day the specified day 65 | * @param goingToRangeStart the start of the going to time 66 | * @param goingToRangeEnd the end of the going to time 67 | * @param leavingRangeStart the start of the leaving time 68 | * @param leavingRangeEnd the end of the leaving time 69 | */ 70 | public Schedule(Profile profile, Day day, LocalTime goingToRangeStart, LocalTime goingToRangeEnd, 71 | LocalTime leavingRangeStart, LocalTime leavingRangeEnd) { 72 | this.profile = profile; 73 | this.day = day; 74 | this.goingToStart = goingToRangeStart; 75 | this.goingToEnd = goingToRangeEnd; 76 | this.leavingStart = leavingRangeStart; 77 | this.leavingEnd = leavingRangeEnd; 78 | } 79 | 80 | /** 81 | * Constructor that takes all parameters except for profile. 82 | * 83 | * @param day the specified day 84 | * @param goingToRangeStart the start of the going to time 85 | * @param goingToRangeEnd the end of the going to time 86 | * @param leavingRangeStart the start of the leaving time 87 | * @param leavingRangeEnd the end of the leaving time 88 | */ 89 | public Schedule(Day day, LocalTime goingToRangeStart, LocalTime goingToRangeEnd, 90 | LocalTime leavingRangeStart, LocalTime leavingRangeEnd) { 91 | this.day = day; 92 | this.goingToStart = goingToRangeStart; 93 | this.goingToEnd = goingToRangeEnd; 94 | this.leavingStart = leavingRangeStart; 95 | this.leavingEnd = leavingRangeEnd; 96 | } 97 | 98 | /** 99 | * Return the id associated with this profile 100 | * 101 | * @return profile id 102 | */ 103 | public int getId() { 104 | return id; 105 | } 106 | 107 | /** 108 | * Return the profile associated with this schedule. 109 | * 110 | * @return the profile 111 | */ 112 | public Profile getProfile() { 113 | return profile; 114 | } 115 | 116 | /** 117 | * Return the day associated with this schedule. 118 | * 119 | * @return the day 120 | */ 121 | public Day getDay() { 122 | return day; 123 | } 124 | 125 | /** 126 | * Sets the day for the schedule to the given day. 127 | * 128 | * @param day the day to set 129 | */ 130 | public void setDay(Day day) { 131 | this.day = day; 132 | } 133 | 134 | /** 135 | * Sets the profile for the schedule to the given profile 136 | * 137 | * @param profile the profile to set 138 | */ 139 | public void setProfile(Profile profile) { 140 | this.profile = profile; 141 | } 142 | 143 | /** 144 | * Return the going to start time for the schedule. 145 | * 146 | * @return the goingToStart 147 | */ 148 | public LocalTime getGoingToStart() { 149 | return goingToStart; 150 | } 151 | 152 | /** 153 | * Sets the going to start time to the given time. 154 | * 155 | * @param goingToStart the goingToStart to set 156 | */ 157 | public void setGoingToStart(LocalTime goingToStart) { 158 | this.goingToStart = goingToStart; 159 | } 160 | 161 | /** 162 | * Return the going to end time for the schedule. 163 | * 164 | * @return the goingToEnd 165 | */ 166 | public LocalTime getGoingToEnd() { 167 | return goingToEnd; 168 | } 169 | 170 | /** 171 | * Sets the going to end time to the given time. 172 | * 173 | * @param goingToEnd the goingToEnd to set 174 | */ 175 | public void setGoingToEnd(LocalTime goingToEnd) { 176 | this.goingToEnd = goingToEnd; 177 | } 178 | 179 | /** 180 | * Return the leaving start time for the schedule. 181 | * 182 | * @return the leavingStart 183 | */ 184 | public LocalTime getLeavingStart() { 185 | return leavingStart; 186 | } 187 | 188 | /** 189 | * Sets the leaving start time to the given time. 190 | * 191 | * @param leavingStart the leavingStart to set 192 | */ 193 | public void setLeavingStart(LocalTime leavingStart) { 194 | this.leavingStart = leavingStart; 195 | } 196 | 197 | /** 198 | * Get the leaving end time for the schedule. 199 | * 200 | * @return Return the leaving end time for the schedule. 201 | */ 202 | public LocalTime getLeavingEnd() { 203 | return leavingEnd; 204 | } 205 | 206 | /** 207 | * Sets the leaving end time to the given time. 208 | * 209 | * @param leavingEnd the leavingEnd to set 210 | */ 211 | public void setLeavingEnd(LocalTime leavingEnd) { 212 | this.leavingEnd = leavingEnd; 213 | } 214 | 215 | /** 216 | * Return the String representation of a schedule. Currently a stub. 217 | * 218 | * @return a String for this schedule 219 | */ 220 | @Override 221 | public String toString() { 222 | return "STUB FOR SCHEDULE"; 223 | } 224 | 225 | /** 226 | * Updates this schedule with the matched times between this schedule and the schedule passed in. 227 | * 228 | * @param schedule the schedule to be compared 229 | * @return true if there was a match, false if there was not a match 230 | */ 231 | public boolean updateWithMatchedTime(Schedule schedule) { 232 | if ((day == schedule.getDay()) 233 | && (goingToEnd.compareTo(schedule.getGoingToStart()) >= 0) 234 | && (schedule.getGoingToEnd().compareTo(goingToStart) >= 0) 235 | && (leavingEnd.compareTo(schedule.getLeavingStart()) >= 0) 236 | && (schedule.getLeavingEnd().compareTo(leavingStart) >= 0)) { 237 | if (goingToStart.isBefore(schedule.getGoingToStart())) 238 | goingToStart = schedule.getGoingToStart(); 239 | if (goingToEnd.isAfter(schedule.getGoingToEnd())) 240 | goingToEnd = schedule.getGoingToEnd(); 241 | if (leavingStart.isBefore(schedule.getLeavingStart())) 242 | leavingStart = schedule.getLeavingStart(); 243 | if (leavingEnd.isAfter(schedule.getLeavingEnd())) 244 | leavingEnd = schedule.getLeavingEnd(); 245 | return true; 246 | } 247 | return false; 248 | } 249 | 250 | 251 | } 252 | 253 | -------------------------------------------------------------------------------- /ruber/lib/matches_screen.dart: -------------------------------------------------------------------------------- 1 | /// matches_screen.dart 2 | /// 3 | /// Purpose: 4 | /// The purpose of this file is to show the matches found depending on the 5 | /// radius set by the user. It shows the user name, the days matched, and 6 | /// the distance they are away from the main user. It uses a listview builder 7 | /// which is a dynamic list created using the length of the returned match 8 | /// profiles JSON. 9 | 10 | /// Imports 11 | import 'dart:async'; 12 | import 'dart:async' show Future; 13 | import 'dart:convert'; 14 | import 'dart:io'; 15 | 16 | import 'package:flutter/material.dart'; 17 | import 'package:http/http.dart' as http; 18 | import 'package:ruber/AppDrawer.dart'; 19 | import 'package:ruber/Constants.dart'; 20 | import 'package:shared_preferences/shared_preferences.dart'; 21 | 22 | import 'ChatRoomScreen.dart'; 23 | import 'ChatroomModel.dart'; 24 | import 'ProfileModel.dart'; 25 | 26 | /// Variable where the returned matched profiles are stored 27 | List profileMatches; 28 | 29 | getId() async { 30 | int id; 31 | if (id == 0 || id == null) { 32 | SharedPreferences prefs = await SharedPreferences.getInstance(); 33 | id = prefs.getInt("id"); 34 | } 35 | ; 36 | return id; 37 | } 38 | 39 | getProfile() { 40 | return profileMatches; 41 | } 42 | 43 | class matchesScreen extends StatefulWidget { 44 | @override 45 | matchesScreenState createState() => new matchesScreenState(); 46 | } 47 | /* 48 | * This method returns the users matches. 49 | */ 50 | class matchesScreenState extends State { 51 | Future> getData() async { 52 | int userId = await getId(); 53 | SharedPreferences prefs = await SharedPreferences.getInstance(); 54 | int radius = prefs.get("radius"); 55 | var response = await http.get( 56 | Uri.encodeFull(BASE_URL + '/rides/matching/$userId/$radius'), 57 | headers: {"Accept": "application/json"}); 58 | 59 | this.setState(() { 60 | profileMatches = json.decode(response.body); 61 | }); 62 | 63 | return allPostsFromJson(response.body); 64 | } 65 | 66 | @override 67 | void initState() { 68 | super.initState(); 69 | this.getData(); 70 | } 71 | 72 | /// This is the widget which is called on when the user clicks a match 73 | /// It shows the full profile (without address), to the user and it 74 | /// allows the user to send them a ride request 75 | 76 | Widget expandProfile(BuildContext context, int index) { 77 | return Scaffold( 78 | appBar: AppBar( 79 | title: Text(profileMatches[index]["name"]), // Name of the person 80 | centerTitle: true, 81 | ), 82 | body: Center( 83 | child: ListView( 84 | children: [ 85 | Container( 86 | margin: EdgeInsets.only( 87 | bottom: 0.0, left: 90.0, right: 90.0, top: 15.0), 88 | width: 150.0, 89 | height: 160.0, 90 | child: new CircleAvatar( 91 | child: new Text( 92 | profileMatches[index]["name"].toString().substring(0, 1), 93 | style: TextStyle(fontSize: 65), 94 | ))), 95 | 96 | /// Full Name 97 | 98 | Container( 99 | margin: EdgeInsets.only(top: 15.0), 100 | child: Text('Full Name', 101 | textAlign: TextAlign.center, 102 | style: TextStyle( 103 | fontWeight: FontWeight.bold, 104 | fontSize: 20.0, 105 | fontFamily: 'Helvetica', 106 | color: Colors.blueAccent))), 107 | 108 | Container( 109 | child: Center(child: Text(profileMatches[index]["name"])), 110 | ), 111 | 112 | Container( 113 | margin: EdgeInsets.only(top: 15.0), 114 | child: Text('Email', 115 | textAlign: TextAlign.center, 116 | style: TextStyle( 117 | fontWeight: FontWeight.bold, 118 | fontSize: 20.0, 119 | fontFamily: 'Helvetica', 120 | color: Colors.deepOrange)), 121 | ), 122 | 123 | Container( 124 | child: Center(child: Text(profileMatches[index]["email"]))), 125 | 126 | Container( 127 | margin: EdgeInsets.only(top: 15.0), 128 | child: Text( 129 | 'Distance', 130 | textAlign: TextAlign.center, 131 | style: TextStyle( 132 | fontWeight: FontWeight.bold, 133 | fontSize: 20.0, 134 | fontFamily: 'Helvetica', 135 | color: Colors.deepPurpleAccent), 136 | )), 137 | 138 | Container( 139 | child: Center( 140 | child: Text( 141 | profileMatches[index]["distanceRounded"].toString() + 142 | " miles"))), 143 | 144 | Container( 145 | margin: EdgeInsets.only(top: 20.0), 146 | child: Center( 147 | child: RaisedButton( 148 | color: Colors.blue, 149 | textColor: Colors.white, 150 | child: Text('Send Ride Request!'), 151 | onPressed: () { 152 | String matchEmail = profileMatches[index]["email"]; 153 | getMatchesId(matchEmail).then((otherId) { 154 | getMyProfileId().then((myId) { 155 | print(myId); 156 | ChatRoom newRoom = new ChatRoom( 157 | profileOneID: myId, profileTwoID: otherId); 158 | createChatRoom(newRoom).then((response) { 159 | if (response.statusCode > 200) 160 | print(response.body); 161 | else 162 | print(response.statusCode); 163 | Navigator.push( 164 | context, 165 | MaterialPageRoute( 166 | builder: (context) => ChatRoomScreen())); 167 | }).catchError((error) { 168 | print('error : $error'); 169 | }); 170 | }).catchError((error) { 171 | print('unable to get id. error : $error'); 172 | }); 173 | }); 174 | }, 175 | ))) 176 | ], 177 | ), 178 | )); 179 | } 180 | 181 | /// This is the main widget that is displayed. It shows a dynamically 182 | /// created list based on the profilematches list. It shows the 183 | /// name, distance, and matched day. 184 | 185 | @override 186 | Widget build(BuildContext context) { 187 | return Scaffold( 188 | appBar: AppBar(title: Text('Matches'), centerTitle: true), 189 | drawer: launchAppDrawer(context), 190 | body: ListView.builder( 191 | itemCount: profileMatches == null ? 0 : profileMatches.length, 192 | itemBuilder: (BuildContext context, int index) { 193 | return new ListTile( 194 | leading: Container( 195 | margin: EdgeInsets.only( 196 | bottom: 0.0, left: 5.0, right: 5.0, top: 0.0), 197 | width: 40.0, 198 | height: 50.0, 199 | child: new CircleAvatar( 200 | child: new Text( 201 | profileMatches[index]["name"].toString().substring(0, 1), 202 | style: TextStyle(fontSize: 20), 203 | ))), 204 | title: Text(profileMatches[index]["name"]), 205 | subtitle: Text( 206 | profileMatches[index]["distanceRounded"].toString() + 207 | " miles " + 208 | profileMatches[index]["schedulesString"].toString()), 209 | onTap: () { 210 | Navigator.push( 211 | context, 212 | MaterialPageRoute( 213 | builder: (context) => expandProfile(context, index))); 214 | }, 215 | ); 216 | })); 217 | } 218 | } 219 | 220 | /* 221 | * This method creates a new chatroom for users that match. 222 | */ 223 | Future createChatRoom(ChatRoom chatroom) async { 224 | int userId = await getId(); 225 | //print(userId); 226 | String newMessageUrl = BASE_URL + '/rides/chatroom/new'; 227 | final response = await http.post('$newMessageUrl', 228 | headers: { 229 | HttpHeaders.contentTypeHeader: 'application/json', 230 | HttpHeaders.authorizationHeader: '' 231 | }, 232 | body: chatroomPostToJson(chatroom)); 233 | print(response.body); 234 | return response; 235 | } 236 | /* 237 | * This method returns the users Id using their email. 238 | */ 239 | 240 | 241 | Future getMatchesId(String tempEmail) async { 242 | String addressUrl = BASE_URL + '/rides/profile/getmyid/$tempEmail'; 243 | final response2 = await http.get(addressUrl); 244 | var res = response2.body; 245 | await setMatchId(int.parse(res)); 246 | print(res); 247 | return int.parse(res); 248 | } 249 | 250 | int matchId; 251 | /* 252 | * This method finds the id of the user they matched with. 253 | */ 254 | getMatchId() async { 255 | SharedPreferences prefs = await SharedPreferences.getInstance(); 256 | int tempId = prefs.getInt("matchID"); 257 | if (tempId != 0 && tempId != null) { 258 | matchId = tempId; 259 | } 260 | 261 | return matchId; 262 | } 263 | 264 | getMatchIdInt() { 265 | return matchId; 266 | } 267 | 268 | setMatchId(int newId) async { 269 | if (newId != null && newId != 0) { 270 | SharedPreferences prefs = await SharedPreferences.getInstance(); 271 | prefs.setInt("matchID", newId); 272 | //print(newId); 273 | matchId = newId; 274 | } 275 | } 276 | 277 | int id; 278 | /* 279 | * This method returns the users id from shared preferences. 280 | */ 281 | Future getMyProfileId() async { 282 | SharedPreferences prefs = await SharedPreferences.getInstance(); 283 | int tempId = prefs.getInt("id"); 284 | if (tempId != 0 && tempId != null) { 285 | id = tempId; 286 | } 287 | 288 | return id; 289 | } 290 | 291 | getMyId() { 292 | return id; 293 | } 294 | -------------------------------------------------------------------------------- /ruber/lib/AuthScreen.dart: -------------------------------------------------------------------------------- 1 | /// AuthScreen.dart 2 | /// 3 | /// Purpose: 4 | /// This file is used for the OAuth functionality for the application. 5 | /// It uses the Google OAuth API to authenticate Rowan users. This handles 6 | /// all GUI for the login, the password management, and we receive a email, 7 | /// full name, and a profile picture from Google as a returned object. 8 | 9 | /// Mandatory Copyright Information 10 | // Copyright 2017 The Chromium Authors. All rights reserved. 11 | // Use of this source code is governed by a BSD-style license that can be 12 | // found in the LICENSE file. 13 | 14 | /// Imports 15 | import 'dart:async'; 16 | import 'dart:async' show Future; 17 | import 'dart:convert'; 18 | import 'dart:io'; 19 | 20 | import 'package:firebase_auth/firebase_auth.dart'; 21 | import 'package:flutter/material.dart'; 22 | import 'package:google_sign_in/google_sign_in.dart'; 23 | import 'package:http/http.dart' as http; 24 | import 'package:ruber/Constants.dart'; 25 | import 'package:shared_preferences/shared_preferences.dart'; 26 | 27 | import 'Main.dart'; 28 | import 'ProfileModel.dart'; 29 | import 'UserModel.dart'; 30 | import 'initialaddaddress.dart'; 31 | 32 | 33 | /// Global variables which are set to the return values from Google 34 | 35 | final FirebaseAuth _auth = FirebaseAuth.instance; 36 | final GoogleSignIn _googleSignIn = GoogleSignIn(); 37 | 38 | String userName; 39 | String firstName; 40 | String userProfilePic; 41 | List profileList; 42 | int id; 43 | Future _message = Future.value(''); 44 | String emailAddress = ""; 45 | 46 | /// Getter and setter methods for the global variables 47 | 48 | getUserProfilePic() async { 49 | SharedPreferences prefs = await SharedPreferences.getInstance(); 50 | String imageUrl = prefs.getString("photo"); 51 | return imageUrl; 52 | } 53 | 54 | getUserName() { 55 | return userName; 56 | } 57 | 58 | getFirstName() { 59 | return firstName; 60 | } 61 | 62 | setUserProfilePic(String newPhotoUrl) async { 63 | userProfilePic = newPhotoUrl; 64 | SharedPreferences prefs = await SharedPreferences.getInstance(); 65 | prefs.setString("photo", newPhotoUrl); 66 | } 67 | 68 | setFirstName(String tempUserName) async { 69 | if (tempUserName.contains(" ")) 70 | tempUserName = tempUserName.substring(0, tempUserName.indexOf(" ")); 71 | SharedPreferences prefs = await SharedPreferences.getInstance(); 72 | prefs.setString("username", tempUserName); 73 | firstName = tempUserName; 74 | } 75 | 76 | setUserName(String tempName) async { 77 | SharedPreferences prefs = await SharedPreferences.getInstance(); 78 | prefs.setString("name", tempName); 79 | userName = tempName; 80 | } 81 | 82 | getMyUserName() async { 83 | SharedPreferences prefs = await SharedPreferences.getInstance(); 84 | String userName = prefs.getString("username"); 85 | return userName; 86 | } 87 | 88 | getEmailAddress() { 89 | return emailAddress; 90 | } 91 | 92 | setEmailAddress(String newEmail) async { 93 | emailAddress = newEmail; 94 | SharedPreferences prefs = await SharedPreferences.getInstance(); 95 | prefs.setString("email", newEmail); 96 | } 97 | 98 | /// The MyAuthScreen class is a StatefulWidget which is extended by 99 | /// the _MyAuthScreenState class. 100 | /// The build Widget handles the GUI screen for the login and handles 101 | /// the flow of the application from one screen to another 102 | class MyAuthScreen extends StatefulWidget { 103 | @override 104 | _MyAuthScreenState createState() => _MyAuthScreenState(); 105 | } 106 | 107 | class _MyAuthScreenState extends State { 108 | String verificationId; 109 | 110 | Future _testSignInWithGoogle() async { 111 | final GoogleSignInAccount googleUser = await _googleSignIn.signIn(); 112 | final GoogleSignInAuthentication googleAuth = 113 | await googleUser.authentication; 114 | final FirebaseUser user = await _auth.signInWithGoogle( 115 | accessToken: googleAuth.accessToken, 116 | idToken: googleAuth.idToken, 117 | ); 118 | assert(user.email != null); 119 | assert(user.displayName != null); 120 | assert(!user.isAnonymous); 121 | assert(await user.getIdToken() != null); 122 | 123 | String tempName = user.displayName.toString(); 124 | String newPhotoUrl = user.photoUrl.toString(); 125 | String tempEmail = user.email.toString(); 126 | 127 | setUserName(tempName); 128 | setFirstName(tempName); 129 | setUserProfilePic(newPhotoUrl); 130 | setEmailAddress(tempEmail); 131 | 132 | final FirebaseUser currentUser = await _auth.currentUser(); 133 | assert(user.uid == currentUser.uid); 134 | 135 | print(getId().toString()); 136 | SharedPreferences prefs = await SharedPreferences.getInstance(); 137 | int tempId = prefs.getInt("id"); 138 | print("temp id: " + tempId.toString()); 139 | 140 | if (tempId == null) { 141 | NewUser tempUser = NewUser(name: tempName, email: tempEmail); 142 | 143 | createUser(tempUser).then((response) { 144 | if (response.statusCode > 200) { 145 | print(tempEmail); 146 | print(response.body); 147 | } else 148 | print(response.statusCode); 149 | }).catchError((error) { 150 | print('error : $error'); 151 | }); 152 | 153 | Navigator.pop(context); 154 | 155 | Navigator.push( 156 | context, 157 | MaterialPageRoute( 158 | builder: (context) => InitialAddressForm( 159 | emailAddress))); 160 | } else { 161 | Navigator.pop(context); 162 | 163 | Navigator.push( 164 | context, MaterialPageRoute(builder: (context) => MainScreen())); 165 | 166 | _loggedIn(); 167 | } 168 | 169 | return 'signInWithGoogle succeeded: $user'; 170 | } 171 | 172 | @override 173 | Widget build(BuildContext context) { 174 | return Scaffold( 175 | appBar: AppBar( 176 | title: Text('Login to Continue'), 177 | centerTitle: true, 178 | ), 179 | body: Center( 180 | child: Column( 181 | children: [ 182 | Image.network( 183 | 'https://www.rowan.edu/home/sites/default/files/styles/basic_page_banner_image/public/sitecontent/page/campuscalendar_page.jpg?itok=W7vURkjO', 184 | ), 185 | MaterialButton( 186 | onPressed: null, 187 | child: const Text( 188 | 'Click "Sign in" below to Log in with your Rowan Gmail Account', 189 | textAlign: TextAlign.center, 190 | ), 191 | textColor: Colors.white, 192 | minWidth: 200.0, 193 | height: 100.0, 194 | ), 195 | MaterialButton( 196 | child: Row( 197 | mainAxisAlignment: MainAxisAlignment.center, 198 | children: [ 199 | Image.network( 200 | 'https://pbs.twimg.com/profile_images/1057899591708753921/PSpUS-Hp_400x400.jpg', 201 | height: 70, 202 | width: 65), 203 | Text( 204 | ' Sign into Ryde with Google', 205 | style: TextStyle(fontSize: 19), 206 | ), 207 | ]), 208 | textColor: Colors.white, 209 | color: Colors.blue, 210 | minWidth: 150.0, 211 | height: 100.0, 212 | onPressed: () { 213 | setState(() { 214 | _message = _testSignInWithGoogle(); 215 | emailAddress = getEmailAddress(); 216 | }); 217 | }, 218 | ), 219 | ], 220 | ), 221 | ), 222 | ); 223 | } 224 | 225 | Future createUser(NewUser user) async { 226 | String updateUrl = BASE_URL + '/rides/profile/new'; 227 | final response = await http.post('$updateUrl', 228 | headers: { 229 | HttpHeaders.contentTypeHeader: 'application/json', 230 | HttpHeaders.authorizationHeader: '' 231 | }, 232 | body: userToJson(user)); 233 | return response; 234 | } 235 | 236 | Future _loggedIn() async { 237 | return showDialog( 238 | context: context, 239 | barrierDismissible: true, 240 | builder: (BuildContext context) { 241 | return AlertDialog( 242 | title: Text( 243 | 'Login Successful!', 244 | textAlign: TextAlign.center, 245 | style: TextStyle(fontWeight: FontWeight.bold, fontSize: 22), 246 | ), 247 | content: SingleChildScrollView( 248 | child: ListBody( 249 | children: [ 250 | Text( 251 | 'Welcome Back, ' + getFirstName() + '!', 252 | textAlign: TextAlign.center, 253 | style: TextStyle(color: Colors.blue, fontSize: 18), 254 | ), 255 | Text(' '), 256 | Container( 257 | margin: EdgeInsets.only( 258 | bottom: 0.0, left: 40.0, right: 40.0, top: 0.0), 259 | width: 90.0, 260 | height: 150.0, 261 | decoration: new BoxDecoration( 262 | shape: BoxShape.circle, 263 | image: new DecorationImage( 264 | fit: BoxFit.fill, 265 | image: NetworkImage(userProfilePic)))), 266 | Text(' '), 267 | Text( 268 | 'Google Account', 269 | textAlign: TextAlign.center, 270 | style: TextStyle( 271 | color: Colors.blue, fontWeight: FontWeight.bold), 272 | ), 273 | Text( 274 | getUserName(), 275 | textAlign: TextAlign.center, 276 | style: TextStyle(color: Colors.blue), 277 | ), 278 | Text( 279 | getEmailAddress(), 280 | textAlign: TextAlign.center, 281 | style: TextStyle(color: Colors.blue), 282 | ), 283 | ], 284 | ), 285 | ), 286 | actions: [ 287 | FlatButton( 288 | child: Text('Close'), 289 | onPressed: () { 290 | Navigator.of(context).pop(); 291 | }, 292 | ), 293 | ], 294 | ); 295 | }, 296 | ); 297 | } 298 | 299 | Future> getAllPost() async { 300 | String postUrl = BASE_URL + '/rides/profile/all'; 301 | final response = await http.get(postUrl); 302 | return allPostsFromJson(response.body); 303 | } 304 | 305 | Future> getData() async { 306 | String postUrl = BASE_URL + '/rides/profile/all'; 307 | final response = await http.get(postUrl); 308 | this.setState(() { 309 | profileList = json.decode(response.body); 310 | }); 311 | 312 | return allPostsFromJson(response.body); 313 | } 314 | 315 | setUserId(int newId) async { 316 | if (newId != null && newId != 0) { 317 | SharedPreferences prefs = await SharedPreferences.getInstance(); 318 | prefs.setInt("id", newId); 319 | id = newId; 320 | } 321 | } 322 | 323 | Future getMyUserId() async { 324 | String addressUrl = BASE_URL + '/rides/profile/getmyid/$emailAddress'; 325 | final response2 = await http.get(addressUrl); 326 | var res = response2.body; 327 | await setUserId(int.parse(res)); 328 | print(res); 329 | return int.parse(res); 330 | } 331 | } 332 | -------------------------------------------------------------------------------- /ruber/lib/initialaddaddress.dart: -------------------------------------------------------------------------------- 1 | /// initialaddress.dart 2 | /// 3 | /// Purpose: 4 | /// The purpose of this file is for the user to be able to input 5 | /// their address into the application. It requires a street name 6 | /// city, zip, and state to move onto the next screen. This is named 7 | /// initial because it is shown at the user creation process 8 | /// and it saves the data to the database as a new user, not an existing 9 | /// user. 10 | 11 | /// Imports 12 | import 'dart:async'; 13 | import 'dart:async' show Future; 14 | import 'dart:io'; 15 | 16 | import 'package:flutter/material.dart'; 17 | import 'package:http/http.dart' as http; 18 | import 'package:ruber/Constants.dart'; 19 | import 'package:shared_preferences/shared_preferences.dart'; 20 | 21 | import 'AddressPostModel.dart'; 22 | import 'AppDrawer.dart'; 23 | import 'initialeditschedule.dart'; 24 | 25 | 26 | /// Global variable declarations for saving the input from the user 27 | int id; 28 | String profilePic; 29 | String streetName = ""; 30 | String city = ""; 31 | String zipCode = ""; 32 | String state = ""; 33 | 34 | String email = ""; 35 | String name = ""; 36 | 37 | /// Shared preferences methods 38 | 39 | getId() async { 40 | 41 | SharedPreferences prefs = await SharedPreferences.getInstance(); 42 | int tempId = prefs.getInt("id"); 43 | if (tempId != 0 && tempId != null) { 44 | id = tempId; 45 | } 46 | 47 | return id; 48 | } 49 | 50 | setId(int newId) async { 51 | if (newId != null && newId != 0) { 52 | SharedPreferences prefs = await SharedPreferences.getInstance(); 53 | prefs.setInt("id", newId); 54 | id = newId; 55 | } 56 | } 57 | 58 | /// Getters and setters for the global variables 59 | 60 | setName(String newName) { 61 | name = newName; 62 | } 63 | 64 | setStreetName(String newStreetName) { 65 | streetName = newStreetName; 66 | } 67 | 68 | setCity(String newCity) { 69 | city = newCity; 70 | } 71 | 72 | setNewState(String newState) { 73 | state = newState; 74 | } 75 | 76 | setZip(String newZip) { 77 | zipCode = newZip; 78 | } 79 | 80 | setProfilePic(String picLocation) { 81 | profilePic = picLocation; 82 | } 83 | 84 | // GETTERS 85 | 86 | getName() { 87 | return name; 88 | } 89 | 90 | getStreetName() { 91 | return streetName; 92 | } 93 | 94 | getCity() { 95 | return city; 96 | } 97 | 98 | getZip() { 99 | return zipCode; 100 | } 101 | 102 | getState() { 103 | return state; 104 | } 105 | 106 | getProfilePic() { 107 | return profilePic; 108 | } 109 | 110 | class InitialAddressForm extends StatefulWidget { 111 | final String emailAddress; 112 | 113 | InitialAddressForm(this.emailAddress); 114 | 115 | @override 116 | _MyAddressForm createState() => _MyAddressForm(); 117 | } 118 | 119 | /// This class holds all the widgets and text controllers (which handle 120 | /// the input from the text forms). It also does error checking 121 | /// so that the user has to populate all the fields in order to 122 | /// move past this screen 123 | 124 | class _MyAddressForm extends State { 125 | final streetNameController = TextEditingController(); 126 | final cityController = TextEditingController(); 127 | final zipController = TextEditingController(); 128 | final stateController = TextEditingController(); 129 | 130 | String newStreet = ""; 131 | String newCity = ""; 132 | String newZip = ""; 133 | String newState = ""; 134 | 135 | bool a = false; 136 | bool b = false; 137 | bool c = false; 138 | bool d = false; 139 | 140 | @override 141 | void dispose() { 142 | streetNameController.dispose(); 143 | cityController.dispose(); 144 | zipController.dispose(); 145 | stateController.dispose(); 146 | 147 | super.dispose(); 148 | } 149 | 150 | @override 151 | Widget build(BuildContext context) { 152 | print(email); 153 | return Scaffold( 154 | appBar: AppBar( 155 | title: Text('Edit your address'), 156 | centerTitle: true, 157 | automaticallyImplyLeading: false), 158 | drawer: launchAppDrawer(context), 159 | body: Center( 160 | child: ListView( 161 | children: [ 162 | Container( 163 | margin: EdgeInsets.all(10.0), 164 | child: Text( 165 | 'Click on each field to edit it', 166 | textAlign: TextAlign.center, 167 | ), 168 | ), 169 | 170 | /// Street Name input 171 | 172 | Container( 173 | margin: EdgeInsets.only(top: 15.0), 174 | child: Text('Street Name', 175 | textAlign: TextAlign.center, 176 | style: TextStyle( 177 | fontWeight: FontWeight.bold, 178 | fontSize: 20.0, 179 | fontFamily: 'Helvetica', 180 | color: Colors.blueAccent))), 181 | Container( 182 | child: TextField( 183 | textAlign: TextAlign.center, 184 | decoration: InputDecoration.collapsed(hintText: streetName), 185 | controller: streetNameController, 186 | onEditingComplete: () { 187 | newStreet = streetNameController.text; 188 | 189 | FocusScope.of(context).requestFocus(new FocusNode()); 190 | }, 191 | )), 192 | 193 | /// City input 194 | 195 | Container( 196 | margin: EdgeInsets.only(top: 15.0), 197 | child: Text('City', 198 | textAlign: TextAlign.center, 199 | style: TextStyle( 200 | fontWeight: FontWeight.bold, 201 | fontSize: 20.0, 202 | fontFamily: 'Helvetica', 203 | color: Colors.blueAccent))), 204 | Container( 205 | child: TextField( 206 | textAlign: TextAlign.center, 207 | decoration: InputDecoration.collapsed(hintText: city), 208 | controller: cityController, 209 | onEditingComplete: () { 210 | 211 | newCity = cityController.text; 212 | 213 | FocusScope.of(context).requestFocus(new FocusNode()); 214 | }, 215 | )), 216 | 217 | /// State input 218 | 219 | Container( 220 | margin: EdgeInsets.only(top: 15.0), 221 | child: Text('State', 222 | textAlign: TextAlign.center, 223 | style: TextStyle( 224 | fontWeight: FontWeight.bold, 225 | fontSize: 20.0, 226 | fontFamily: 'Helvetica', 227 | color: Colors.blueAccent))), 228 | Container( 229 | child: TextField( 230 | textAlign: TextAlign.center, 231 | decoration: InputDecoration.collapsed(hintText: state), 232 | controller: stateController, 233 | onEditingComplete: () { 234 | // Make sure to write to Database 235 | 236 | newState = stateController.text; 237 | 238 | FocusScope.of(context).requestFocus(new FocusNode()); 239 | }, 240 | )), 241 | 242 | /// ZIP code input 243 | 244 | Container( 245 | margin: EdgeInsets.only(top: 15.0), 246 | child: Text('ZIP', 247 | textAlign: TextAlign.center, 248 | style: TextStyle( 249 | fontWeight: FontWeight.bold, 250 | fontSize: 20.0, 251 | fontFamily: 'Helvetica', 252 | color: Colors.blueAccent))), 253 | Container( 254 | child: TextField( 255 | textAlign: TextAlign.center, 256 | decoration: InputDecoration.collapsed(hintText: zipCode), 257 | controller: zipController, 258 | onEditingComplete: () { 259 | // Make sure to write to Database 260 | newZip = zipController.text; 261 | 262 | FocusScope.of(context).requestFocus(new FocusNode()); 263 | }, 264 | )), 265 | 266 | /// Save address button - does error checking to make sure 267 | /// that the user had populated all the fields before clicking 268 | /// on the button 269 | 270 | Container( 271 | margin: EdgeInsets.only(top: 40.0, left: 70.0, right: 70.0), 272 | child: RaisedButton( 273 | color: Colors.blue, 274 | textColor: Colors.white, 275 | child: Text('Save Address'), 276 | onPressed: () { 277 | 278 | if (streetNameController.text.isEmpty != true) { 279 | setStreetName(streetNameController.text); 280 | a = true; 281 | } 282 | if (stateController.text.isEmpty != true) { 283 | setNewState(stateController.text); 284 | b = true; 285 | } 286 | if (cityController.text.isEmpty != true) { 287 | setCity(cityController.text); 288 | c = true; 289 | } 290 | if (zipController.text.isEmpty != true) { 291 | setZip(zipController.text); 292 | d = true; 293 | } 294 | 295 | // Only activates after all the fields have information in them 296 | if (true) { 297 | String streetNameEdit = getStreetName(); 298 | String cityNameFinal = getCity(); 299 | String zipCodeEdit = getZip(); 300 | String stateEdit = getState(); 301 | AddressPost newAddress = AddressPost( 302 | streetAddress: streetNameEdit, 303 | city: cityNameFinal, 304 | zipCode: zipCodeEdit, 305 | state: 306 | stateEdit); // creating a new Post object to send it to API 307 | 308 | createAddress(newAddress).then((response) { 309 | if (response.statusCode > 200) 310 | print(response.body); 311 | else 312 | print(response.statusCode); 313 | }).catchError((error) { 314 | print('error : $error'); 315 | }); 316 | 317 | print(newAddress.toString()); 318 | 319 | Navigator.push( 320 | context, 321 | MaterialPageRoute( 322 | builder: (context) => InitialScheduleForm()), 323 | ); 324 | } 325 | }, 326 | )), 327 | ], 328 | ))); 329 | } 330 | } 331 | 332 | /* 333 | * This method returns the users id using their email from shared preferences. 334 | */ 335 | Future getMyId() async { 336 | SharedPreferences prefs = await SharedPreferences.getInstance(); 337 | String emailUrl = prefs.getString("email"); 338 | 339 | //String emailUrl = ; // Need to work on getting email from AuthScreen.dart 340 | String addressUrl = BASE_URL + '/rides/profile/getmyid/$emailUrl'; 341 | final response2 = await http.get(addressUrl); 342 | var res = response2.body; 343 | await setId(int.parse(res)); 344 | print(res); 345 | return int.parse(res); 346 | } 347 | /* 348 | * This method adds the users new address to their profile on the server. 349 | */ 350 | Future createAddress(AddressPost address) async { 351 | int userId = await getId(); 352 | print(userId); 353 | String updateUrl = BASE_URL + '/rides/address/$userId/new'; 354 | final response = await http.post('$updateUrl', 355 | headers: { 356 | HttpHeaders.contentTypeHeader: 'application/json', 357 | HttpHeaders.authorizationHeader: '' 358 | }, 359 | body: addressPostToJson(address)); 360 | return response; 361 | } 362 | -------------------------------------------------------------------------------- /ruber/lib/ChatRoomScreen.dart: -------------------------------------------------------------------------------- 1 | /// ChatRoomScreen.dart 2 | /// 3 | /// Purpose: 4 | /// This file is used to show the different chat threads once the user 5 | /// clicks on the "Messages" option from the main menu. It also includes 6 | /// the screen which allows the user to type in a message and send it 7 | /// to the opposing user. 8 | 9 | /// Imports 10 | import 'dart:async'; 11 | import 'dart:async' show Future; 12 | import 'dart:convert'; 13 | import 'dart:io'; 14 | 15 | import 'package:flutter/material.dart'; 16 | import 'package:http/http.dart' as http; 17 | import 'package:shared_preferences/shared_preferences.dart'; 18 | 19 | import 'AppDrawer.dart'; 20 | import 'AuthScreen.dart'; 21 | import 'ChatroomModel.dart'; 22 | import 'Constants.dart'; 23 | 24 | /// Global variables for storing the chat rooms from the server 25 | 26 | Map profileChats; 27 | String myInputText; 28 | 29 | int chatRoomId; 30 | 31 | /// Getter and setter methods 32 | 33 | getChatRoomId() { 34 | return chatRoomId; 35 | } 36 | 37 | setChatRoomId(int tempID) { 38 | chatRoomId = tempID; 39 | } 40 | 41 | getProfiles() { 42 | return profileChats; 43 | } 44 | 45 | getMyInputText() { 46 | return myInputText; 47 | } 48 | 49 | setMyInputText(String tempInput) { 50 | myInputText = tempInput; 51 | } 52 | 53 | class ChatRoomScreen extends StatefulWidget { 54 | @override 55 | ChatRoomScreenState createState() => new ChatRoomScreenState(); 56 | } 57 | 58 | /// ChatRoomScreenState class holds all the Widgets for the chat room 59 | /// functionality. 60 | /// Widgets in ChatRoomScreenState: 61 | /// Chat Threads Screen - build() 62 | /// 63 | class ChatRoomScreenState extends State { 64 | 65 | int index; 66 | Future getData() async { 67 | int userId = await getId(); 68 | SharedPreferences prefs = await SharedPreferences.getInstance(); 69 | 70 | var response = await http.get( 71 | 72 | /// Change the URL to the end point from the database 73 | Uri.encodeFull(BASE_URL + '/rides/profile/$userId/chatrooms'), 74 | headers: {"Accept": "application/json"}); 75 | 76 | this.setState(() { 77 | profileChats = json.decode(response.body); 78 | }); 79 | 80 | return listFromJsonChat(response.body); 81 | } 82 | 83 | @override 84 | void initState() { 85 | super.initState(); 86 | this.getData(); 87 | } 88 | 89 | /// Chat Thread screen -- initial screen which is shown whenever 90 | /// the user clicks on the "Messages" option 91 | 92 | @override 93 | Widget build(BuildContext context) { 94 | return Scaffold( 95 | appBar: AppBar( 96 | title: Text('Messages'), 97 | centerTitle: true, 98 | ), 99 | drawer: launchAppDrawer(context), 100 | body: ListView.builder( 101 | itemCount: 102 | profileChats == null ? 0 : profileChats["chatrooms"].length, 103 | itemBuilder: (BuildContext context, int index) { 104 | int chatid = profileChats["chatrooms"][index]["chatRoomId"]; 105 | setChatRoomId(chatid); 106 | return new ListTile( 107 | leading: Container( 108 | margin: EdgeInsets.only( 109 | bottom: 5.0, left: 5.0, right: 5.0, top: 5.0), 110 | width: 40.0, 111 | height: 50.0, 112 | child: new CircleAvatar( 113 | child: new Text( 114 | profileChats["chatrooms"][index]["profileNames"] 115 | ["Profile 2"] 116 | .toString() 117 | .substring(0, 1) + 118 | profileChats["chatrooms"][index]["profileNames"] 119 | ["Profile 1"] 120 | .toString() 121 | .substring(0, 1), 122 | style: TextStyle(fontSize: 20), 123 | ))), 124 | title: Text(profileChats["chatrooms"][index]["profileNames"] 125 | ["Profile 2"] 126 | .toString() + 127 | " & " + 128 | profileChats["chatrooms"][index]["profileNames"]["Profile 1"] 129 | .toString()), 130 | onTap: () { 131 | Navigator.push( 132 | context, 133 | MaterialPageRoute( 134 | builder: (context) => 135 | IndividualChatThread(context, index))); 136 | }, 137 | ); 138 | }, 139 | )); 140 | } 141 | 142 | /// Text Editing Controller - for holding the message that was typed 143 | 144 | TextEditingController _textController = new TextEditingController(); 145 | 146 | void _afterMessageSubmission(String text) { 147 | setState(() { 148 | if (_textController.text.isEmpty) { 149 | } else 150 | setMyInputText(_textController.text); 151 | }); 152 | } 153 | 154 | /// This widget holds the different messages from both parties - also 155 | /// shows the time sent/received and their profile image 156 | 157 | Widget MessageContainer() { 158 | return new IconTheme( 159 | data: new IconThemeData(color: Theme.of(context).accentColor), 160 | child: new Container( 161 | margin: const EdgeInsets.symmetric(horizontal: 8.0), 162 | child: new Row( 163 | children: [ 164 | new Flexible( 165 | child: new TextField( 166 | controller: _textController, 167 | onChanged: _afterMessageSubmission, 168 | onSubmitted: _afterMessageSubmission, 169 | decoration: 170 | new InputDecoration.collapsed(hintText: "Send a message"), 171 | ), 172 | ), 173 | new Container( 174 | margin: new EdgeInsets.symmetric(horizontal: 8.0), 175 | child: new IconButton( 176 | icon: new Icon(Icons.send), 177 | onPressed: () { 178 | String newText = getMyInputText(); 179 | Messages newMessage = Messages( 180 | chatroomID: getChatRoomId(), 181 | senderID: id, 182 | text: newText); 183 | createMessage(newMessage).then((response) { 184 | if (response.statusCode > 200) 185 | print(response.body); 186 | else 187 | print(response.statusCode); 188 | 189 | getData().then((res) { 190 | Navigator.push( 191 | context, 192 | MaterialPageRoute( 193 | builder: (context) => 194 | IndividualChatThread(context, index))); 195 | }); 196 | 197 | }).catchError((error) { 198 | print('error : $error'); 199 | }); 200 | _textController.clear(); 201 | }), 202 | ), 203 | ], 204 | ), 205 | )); 206 | } 207 | 208 | /// This is the screen shown when the user clicks onto a chat thread 209 | /// in the chat room screen. It holds the MessageContainer inside it 210 | /// so that it can show the different messages being typed 211 | 212 | Widget IndividualChatThread(BuildContext context, int index) { 213 | this.index = index; 214 | return Scaffold( 215 | appBar: AppBar( 216 | title: Text(profileChats["chatrooms"][index]["profileNames"] 217 | ["Profile 2"] 218 | .toString() + 219 | " & " + 220 | profileChats["chatrooms"][index]["profileNames"]["Profile 1"] 221 | .toString()), 222 | centerTitle: true, 223 | actions: [ 224 | IconButton( 225 | icon: Icon(Icons.refresh), 226 | onPressed: () { 227 | 228 | getData().then((res) { 229 | Navigator.push( 230 | context, 231 | MaterialPageRoute( 232 | builder: (context) => 233 | IndividualChatThread(context, index))); 234 | }); 235 | 236 | }) 237 | 238 | ]), 239 | drawer: launchAppDrawer(context), 240 | body: new Column( 241 | children: [ 242 | Flexible( 243 | child: ListView.builder( 244 | padding: new EdgeInsets.all(15.0), 245 | reverse: true, 246 | itemCount: profileChats == null 247 | ? 0 248 | : profileChats["chatrooms"][index]["messages"].length, 249 | itemBuilder: (BuildContext context, int index2) { 250 | return Container( 251 | 252 | /// This logic decides where the messages go in the 253 | /// MessageContainer - right or left. Right is for the 254 | /// sender, left is for the received messages. It does 255 | /// this by comparing the senderID of the message being 256 | /// sent to the profileID of the user of the app. If they 257 | /// are equal, then it means that the sender is the user 258 | /// so it goes on the right hand side, and ANY other message 259 | /// goes on the left hand side (receiver messages) 260 | 261 | child: Row( 262 | children: profileChats["chatrooms"][index]["messages"] 263 | [index2]["senderID"] == 264 | id 265 | ? rightSide(index, index2) 266 | : leftSide(index, index2))); 267 | }, 268 | ), 269 | ), 270 | Divider(height: 0.0), 271 | Container( 272 | child: MessageContainer(), 273 | decoration: 274 | new BoxDecoration(color: Theme.of(context).cardColor)) 275 | ], 276 | )); 277 | } 278 | 279 | /// This is for structuring the message to go on the right side, if 280 | /// the message is being sent by the user of the app - currently 281 | /// Received messages from the other party are displayed on the left 282 | /// hand side 283 | 284 | List rightSide(int index, int index2) { 285 | return [ 286 | Expanded( 287 | child: Column( 288 | crossAxisAlignment: CrossAxisAlignment.end, 289 | children: [ 290 | new Container( 291 | margin: const EdgeInsets.only(top: 15.0), 292 | child: Container( 293 | child: FutureBuilder( 294 | future: getChatrooms(), 295 | builder: (context, snapshot) { 296 | return Text( 297 | profileChats["chatrooms"][index]["messages"] 298 | [index2]["text"] 299 | .toString(), 300 | style: TextStyle( 301 | fontSize: 18.0, 302 | color: Colors.lightBlue, 303 | fontWeight: FontWeight.bold)); 304 | }))), 305 | new Container( 306 | margin: const EdgeInsets.only(top: 10.0), 307 | child: Container( 308 | child: FutureBuilder( 309 | future: getChatrooms(), 310 | builder: (context, snapshot) { 311 | return Text( 312 | profileChats["chatrooms"][index]["messages"] 313 | [index2]["timeSent"] 314 | .toString(), 315 | style: TextStyle( 316 | fontSize: 14.0, 317 | color: Colors.grey, 318 | fontWeight: FontWeight.normal)); 319 | }))), 320 | ], 321 | ), 322 | ), 323 | Column( 324 | crossAxisAlignment: CrossAxisAlignment.end, 325 | children: [ 326 | new Container( 327 | margin: 328 | EdgeInsets.only(bottom: 0.0, left: 5.0, right: 5.0, top: 0.0), 329 | width: 42.0, 330 | height: 38.0, 331 | decoration: new BoxDecoration( 332 | shape: BoxShape.circle, 333 | image: new DecorationImage( 334 | fit: BoxFit.fill, 335 | // This is where we would retrieve the image from the data base 336 | image: NetworkImage(userProfilePic)))), 337 | ], 338 | ) 339 | ]; 340 | } 341 | 342 | /// This is used to structure the message on the left hand side -- for 343 | /// received messages. Sent messages are displayed on the right hand side. 344 | 345 | List leftSide(int index, int index2) { 346 | return [ 347 | Column( 348 | crossAxisAlignment: CrossAxisAlignment.start, 349 | children: [ 350 | new Container( 351 | margin: 352 | EdgeInsets.only(bottom: 0.0, left: 0.0, right: 5.0, top: 0.0), 353 | width: 40.0, 354 | height: 50.0, 355 | child: new CircleAvatar( 356 | child: new Text( 357 | profileChats["chatrooms"][index]["profileNames"]["Profile 2"] 358 | .toString() 359 | .substring(0, 1), 360 | style: TextStyle(fontSize: 20), 361 | ))), 362 | ], 363 | ), 364 | Expanded( 365 | child: Column( 366 | crossAxisAlignment: CrossAxisAlignment.start, 367 | children: [ 368 | new Container( 369 | margin: const EdgeInsets.only(top: 15.0), 370 | child: Container( 371 | child: FutureBuilder( 372 | future: getChatrooms(), 373 | builder: (context, snapshot) { 374 | return Text( 375 | profileChats["chatrooms"][index]["messages"] 376 | [index2]["text"] 377 | .toString(), 378 | style: TextStyle( 379 | fontSize: 18.0, 380 | color: Colors.lightBlue, 381 | fontWeight: FontWeight.bold)); 382 | }))), 383 | new Container( 384 | margin: const EdgeInsets.only(top: 5.0), 385 | child: Container( 386 | child: FutureBuilder( 387 | future: getChatrooms(), 388 | builder: (context, snapshot) { 389 | return Text( 390 | profileChats["chatrooms"][index]["messages"] 391 | [index2]["timeSent"] 392 | .toString(), 393 | style: TextStyle( 394 | fontSize: 14.0, 395 | color: Colors.grey, 396 | fontWeight: FontWeight.normal)); 397 | }))), 398 | ], 399 | ), 400 | ) 401 | ]; 402 | } 403 | } 404 | 405 | /* 406 | * This method is used to get the users Id from shared Preferences 407 | */ 408 | getId() async { 409 | SharedPreferences prefs = await SharedPreferences.getInstance(); 410 | int tempId = prefs.getInt("id"); 411 | if (tempId != 0 && tempId != null) { 412 | id = tempId; 413 | } 414 | return id; 415 | } 416 | /* 417 | * This Method is used to return all of the chatrooms the user is part of. 418 | */ 419 | Future getChatrooms() async { 420 | int userid = await getId(); 421 | String postUrl = BASE_URL + '/rides/profile/$userid/chatrooms'; 422 | final response = await http.get(postUrl); 423 | return listFromJsonChat(response.body); 424 | } 425 | /* 426 | *This method is used to post messages to the server. 427 | */ 428 | Future createMessage(Messages myMessage) async { 429 | String newMessageUrl = BASE_URL + '/rides/message/new'; 430 | final response = await http.post('$newMessageUrl', 431 | headers: { 432 | HttpHeaders.contentTypeHeader: 'application/json', 433 | HttpHeaders.authorizationHeader: '' 434 | }, 435 | body: messagePostToJson(myMessage)); 436 | return response; 437 | } 438 | --------------------------------------------------------------------------------