├── .gitignore
├── LICENSE
├── README.md
├── frontend
├── BirdAtlas.Android
│ ├── Assets
│ │ ├── AboutAssets.txt
│ │ ├── Montserrat-Light.ttf
│ │ ├── Montserrat-Medium.ttf
│ │ ├── Montserrat-Regular.ttf
│ │ ├── Montserrat-SemiBold.ttf
│ │ └── materialdesignicons-webfont.ttf
│ ├── BirdAtlas.Android.csproj
│ ├── Framework
│ │ └── DeviceInfo.cs
│ ├── MainActivity.cs
│ ├── Properties
│ │ ├── AndroidManifest.xml
│ │ └── AssemblyInfo.cs
│ └── Resources
│ │ ├── AboutResources.txt
│ │ ├── Resource.designer.cs
│ │ ├── layout
│ │ ├── Tabbar.axml
│ │ └── Toolbar.axml
│ │ ├── mipmap-anydpi-v26
│ │ ├── icon.xml
│ │ └── icon_round.xml
│ │ ├── mipmap-hdpi
│ │ ├── icon.png
│ │ └── launcher_foreground.png
│ │ ├── mipmap-mdpi
│ │ ├── icon.png
│ │ └── launcher_foreground.png
│ │ ├── mipmap-xhdpi
│ │ ├── icon.png
│ │ └── launcher_foreground.png
│ │ ├── mipmap-xxhdpi
│ │ ├── icon.png
│ │ └── launcher_foreground.png
│ │ ├── mipmap-xxxhdpi
│ │ ├── icon.png
│ │ └── launcher_foreground.png
│ │ └── values
│ │ ├── colors.xml
│ │ └── styles.xml
├── BirdAtlas.iOS
│ ├── AppDelegate.cs
│ ├── Assets.xcassets
│ │ └── AppIcon.appiconset
│ │ │ ├── Contents.json
│ │ │ ├── Icon1024.png
│ │ │ ├── Icon120.png
│ │ │ ├── Icon152.png
│ │ │ ├── Icon167.png
│ │ │ ├── Icon180.png
│ │ │ ├── Icon20.png
│ │ │ ├── Icon29.png
│ │ │ ├── Icon40.png
│ │ │ ├── Icon58.png
│ │ │ ├── Icon60.png
│ │ │ ├── Icon76.png
│ │ │ ├── Icon80.png
│ │ │ └── Icon87.png
│ ├── BirdAtlas.iOS.csproj
│ ├── Entitlements.plist
│ ├── Framework
│ │ └── DeviceInfo.cs
│ ├── Info.plist
│ ├── Main.cs
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ ├── Resources
│ │ ├── Default-568h@2x.png
│ │ ├── Default-Portrait.png
│ │ ├── Default-Portrait@2x.png
│ │ ├── Default.png
│ │ ├── Default@2x.png
│ │ ├── LaunchScreen.storyboard
│ │ ├── Montserrat-Light.ttf
│ │ ├── Montserrat-Medium.ttf
│ │ ├── Montserrat-Regular.ttf
│ │ ├── Montserrat-SemiBold.ttf
│ │ ├── ic_bookmarks.png
│ │ ├── ic_bookmarks@2x.png
│ │ ├── ic_bookmarks@3x.png
│ │ ├── ic_discover.png
│ │ ├── ic_discover@2x.png
│ │ ├── ic_discover@3x.png
│ │ ├── ic_search.png
│ │ ├── ic_search@2x.png
│ │ ├── ic_search@3x.png
│ │ └── materialdesignicons-webfont.ttf
│ └── mono_crash.115869eaf6.0.json
├── BirdAtlas.sln
└── BirdAtlas
│ ├── App.xaml
│ ├── App.xaml.cs
│ ├── Behaviors
│ └── EntranceBehavior.cs
│ ├── BirdAtlas.csproj
│ ├── Converters
│ └── HabitatTypeToColorConverter.cs
│ ├── Extensions
│ └── IEnumerableExtensions.cs
│ ├── Framework
│ └── IDeviceInfo.cs
│ ├── Models
│ ├── Enums.cs
│ ├── Habitat.cs
│ ├── IconFont.cs
│ ├── Nearby.cs
│ └── Story.cs
│ ├── Services
│ ├── BirdAtlasMockAPI.cs
│ └── IBirdAtlasAPI.cs
│ ├── ViewModels
│ ├── BaseViewModel.cs
│ ├── BookmarkViewModel.cs
│ ├── DiscoverViewModel.cs
│ ├── SearchViewModel.cs
│ ├── SettingsViewModel.cs
│ ├── StartViewModel.cs
│ ├── StoryDetailViewModel.cs
│ └── StoryOverviewViewModel.cs
│ ├── Views
│ ├── BasePage.xaml
│ ├── BasePage.xaml.cs
│ ├── SettingsPage.xaml
│ ├── SettingsPage.xaml.cs
│ ├── StartPage.xaml
│ ├── StartPage.xaml.cs
│ ├── StoryDetailPage.xaml
│ ├── StoryDetailPage.xaml.cs
│ ├── StoryOverviewPage.xaml
│ ├── StoryOverviewPage.xaml.cs
│ └── TabViews
│ │ ├── BookmarkTabView.xaml
│ │ ├── BookmarkTabView.xaml.cs
│ │ ├── DiscoverTabView.xaml
│ │ ├── DiscoverTabView.xaml.cs
│ │ ├── SearchTabView.xaml
│ │ └── SearchTabView.xaml.cs
│ └── XamlResources
│ ├── DataTemplates.xaml
│ ├── DataTemplates.xaml.cs
│ ├── Styles.xaml
│ └── Styles.xaml.cs
├── frontend_flutter
├── .gitignore
├── .metadata
├── .vscode
│ ├── launch.json
│ └── settings.json
├── README.md
├── analysis_options.yaml
├── android
│ ├── .gitignore
│ ├── app
│ │ ├── build.gradle
│ │ └── src
│ │ │ ├── main
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── kotlin
│ │ │ │ └── com
│ │ │ │ │ └── example
│ │ │ │ │ └── frontend_flutter
│ │ │ │ │ └── MainActivity.kt
│ │ │ └── res
│ │ │ │ ├── drawable-v21
│ │ │ │ └── launch_background.xml
│ │ │ │ ├── drawable
│ │ │ │ └── launch_background.xml
│ │ │ │ ├── mipmap-hdpi
│ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-mdpi
│ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-xhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-xxhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-xxxhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ │ ├── values-night
│ │ │ │ └── styles.xml
│ │ │ │ └── values
│ │ │ │ └── styles.xml
│ │ │ └── profile
│ │ │ └── AndroidManifest.xml
│ ├── build.gradle
│ ├── gradle.properties
│ ├── gradle
│ │ └── wrapper
│ │ │ └── gradle-wrapper.properties
│ └── settings.gradle
├── fonts
│ ├── Montserrat-Light.ttf
│ ├── Montserrat-Medium.ttf
│ ├── Montserrat-Regular.ttf
│ └── Montserrat-SemiBold.ttf
├── ios
│ ├── .gitignore
│ ├── Flutter
│ │ ├── AppFrameworkInfo.plist
│ │ ├── Debug.xcconfig
│ │ └── Release.xcconfig
│ ├── Runner.xcodeproj
│ │ ├── project.pbxproj
│ │ ├── project.xcworkspace
│ │ │ ├── contents.xcworkspacedata
│ │ │ └── xcshareddata
│ │ │ │ ├── IDEWorkspaceChecks.plist
│ │ │ │ └── WorkspaceSettings.xcsettings
│ │ └── xcshareddata
│ │ │ └── xcschemes
│ │ │ └── Runner.xcscheme
│ ├── Runner.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ ├── IDEWorkspaceChecks.plist
│ │ │ └── WorkspaceSettings.xcsettings
│ └── Runner
│ │ ├── AppDelegate.swift
│ │ ├── Assets.xcassets
│ │ ├── AppIcon.appiconset
│ │ │ ├── Contents.json
│ │ │ ├── Icon-App-1024x1024@1x.png
│ │ │ ├── Icon-App-20x20@1x.png
│ │ │ ├── Icon-App-20x20@2x.png
│ │ │ ├── Icon-App-20x20@3x.png
│ │ │ ├── Icon-App-29x29@1x.png
│ │ │ ├── Icon-App-29x29@2x.png
│ │ │ ├── Icon-App-29x29@3x.png
│ │ │ ├── Icon-App-40x40@1x.png
│ │ │ ├── Icon-App-40x40@2x.png
│ │ │ ├── Icon-App-40x40@3x.png
│ │ │ ├── Icon-App-60x60@2x.png
│ │ │ ├── Icon-App-60x60@3x.png
│ │ │ ├── Icon-App-76x76@1x.png
│ │ │ ├── Icon-App-76x76@2x.png
│ │ │ └── Icon-App-83.5x83.5@2x.png
│ │ └── LaunchImage.imageset
│ │ │ ├── Contents.json
│ │ │ ├── LaunchImage.png
│ │ │ ├── LaunchImage@2x.png
│ │ │ ├── LaunchImage@3x.png
│ │ │ └── README.md
│ │ ├── Base.lproj
│ │ ├── LaunchScreen.storyboard
│ │ └── Main.storyboard
│ │ ├── Info.plist
│ │ └── Runner-Bridging-Header.h
├── lib
│ ├── main.dart
│ ├── main
│ │ ├── mainPage.dart
│ │ └── tabs
│ │ │ ├── bookmarkTab.dart
│ │ │ ├── discoverTab.dart
│ │ │ ├── searchTab.dart
│ │ │ └── tabAppBar.dart
│ ├── models.dart
│ ├── services
│ │ ├── birdatlasAPIInterface.dart
│ │ └── birdatlasAPIMocked.dart
│ └── styles.dart
├── pubspec.lock
└── pubspec.yaml
└── frontend_maui
├── BirdAtlasMaui.sln
└── BirdAtlasMaui
├── App.xaml
├── App.xaml.cs
├── BirdAtlasMaui.csproj
├── Client
└── RestServiceFactory.cs
├── Constants
└── Constants.cs
├── Models
├── Bird.cs
├── Habitat.cs
├── HabitatType.cs
└── Story.cs
├── Platforms
├── Android
│ ├── AndroidManifest.xml
│ ├── MainActivity.cs
│ ├── MainApplication.cs
│ └── Resources
│ │ └── values
│ │ ├── colors.xml
│ │ └── styles.xml
├── MacCatalyst
│ ├── AppDelegate.cs
│ ├── Info.plist
│ └── Program.cs
└── iOS
│ ├── AppDelegate.cs
│ ├── Info.plist
│ ├── Program.cs
│ └── Resources
│ └── LaunchScreen.xib
├── Resources
├── Fonts
│ └── OpenSans-Regular.ttf
├── Images
│ └── dotnet_bot.svg
├── appicon.svg
└── appiconfg.svg
├── Services
├── API
│ ├── IBirdApi.cs
│ ├── IHabitatApi.cs
│ └── IStoryApi.cs
├── BirdService.cs
├── HabitatService.cs
└── StoryService.cs
├── Startup.cs
├── ViewModels
├── BaseViewModel.cs
├── BirdViewModel.cs
├── MainViewModel.cs
└── StoriesViewModel.cs
└── Views
├── BirdPage.xaml
├── BirdPage.xaml.cs
├── MainPage.xaml
├── MainPage.xaml.cs
├── StoriesPage.xaml
└── StoriesPage.xaml.cs
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # BirdAtlas
2 |
3 | ## Design
4 | Based upon [Dribbble project](https://dribbble.com/shots/5442850-Bird-Atlas-App) created by [Monika Michalczyk](https://dribbble.com/michalczyk)
5 |
6 | 
--------------------------------------------------------------------------------
/frontend/BirdAtlas.Android/Assets/AboutAssets.txt:
--------------------------------------------------------------------------------
1 | Any raw assets you want to be deployed with your application can be placed in
2 | this directory (and child directories) and given a Build Action of "AndroidAsset".
3 |
4 | These files will be deployed with you package and will be accessible using Android's
5 | AssetManager, like this:
6 |
7 | public class ReadAsset : Activity
8 | {
9 | protected override void OnCreate (Bundle bundle)
10 | {
11 | base.OnCreate (bundle);
12 |
13 | InputStream input = Assets.Open ("my_asset.txt");
14 | }
15 | }
16 |
17 | Additionally, some Android functions will automatically load asset files:
18 |
19 | Typeface tf = Typeface.CreateFromAsset (Context.Assets, "fonts/samplefont.ttf");
20 |
--------------------------------------------------------------------------------
/frontend/BirdAtlas.Android/Assets/Montserrat-Light.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend/BirdAtlas.Android/Assets/Montserrat-Light.ttf
--------------------------------------------------------------------------------
/frontend/BirdAtlas.Android/Assets/Montserrat-Medium.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend/BirdAtlas.Android/Assets/Montserrat-Medium.ttf
--------------------------------------------------------------------------------
/frontend/BirdAtlas.Android/Assets/Montserrat-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend/BirdAtlas.Android/Assets/Montserrat-Regular.ttf
--------------------------------------------------------------------------------
/frontend/BirdAtlas.Android/Assets/Montserrat-SemiBold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend/BirdAtlas.Android/Assets/Montserrat-SemiBold.ttf
--------------------------------------------------------------------------------
/frontend/BirdAtlas.Android/Assets/materialdesignicons-webfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend/BirdAtlas.Android/Assets/materialdesignicons-webfont.ttf
--------------------------------------------------------------------------------
/frontend/BirdAtlas.Android/Framework/DeviceInfo.cs:
--------------------------------------------------------------------------------
1 | using BirdAtlas.Droid.Framework;
2 | using BirdAtlas.Framework;
3 | using Xamarin.Forms;
4 |
5 | [assembly: Dependency(typeof(DeviceInfo))]
6 | namespace BirdAtlas.Droid.Framework
7 | {
8 | public class DeviceInfo : IDeviceInfo
9 | {
10 | public float StatusbarHeight => 0;
11 | }
12 | }
--------------------------------------------------------------------------------
/frontend/BirdAtlas.Android/MainActivity.cs:
--------------------------------------------------------------------------------
1 | using Android.App;
2 | using Android.Content.PM;
3 | using Android.OS;
4 | using Sharpnado.HorizontalListView.Droid;
5 | using Xamarin.Forms;
6 |
7 | namespace BirdAtlas.Droid
8 | {
9 | [Activity(Label = "BirdAtlas", Icon = "@mipmap/icon", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
10 | public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
11 | {
12 | protected override void OnCreate(Bundle savedInstanceState)
13 | {
14 | TabLayoutResource = Resource.Layout.Tabbar;
15 | ToolbarResource = Resource.Layout.Toolbar;
16 |
17 | base.OnCreate(savedInstanceState);
18 | Forms.SetFlags("CollectionView_Experimental");
19 | global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
20 |
21 | SharpnadoInitializer.Initialize(enableInternalLogger: true, enableInternalDebugLogger: true);
22 |
23 | LoadApplication(new App());
24 | }
25 | }
26 | }
--------------------------------------------------------------------------------
/frontend/BirdAtlas.Android/Properties/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/frontend/BirdAtlas.Android/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 | using Android.App;
5 |
6 | // General Information about an assembly is controlled through the following
7 | // set of attributes. Change these attribute values to modify the information
8 | // associated with an assembly.
9 | [assembly: AssemblyTitle("BirdAtlas.Android")]
10 | [assembly: AssemblyDescription("")]
11 | [assembly: AssemblyConfiguration("")]
12 | [assembly: AssemblyCompany("")]
13 | [assembly: AssemblyProduct("BirdAtlas.Android")]
14 | [assembly: AssemblyCopyright("Copyright © 2014")]
15 | [assembly: AssemblyTrademark("")]
16 | [assembly: AssemblyCulture("")]
17 | [assembly: ComVisible(false)]
18 |
19 | // Version information for an assembly consists of the following four values:
20 | //
21 | // Major Version
22 | // Minor Version
23 | // Build Number
24 | // Revision
25 | //
26 | // You can specify all the values or you can default the Build and Revision Numbers
27 | // by using the '*' as shown below:
28 | // [assembly: AssemblyVersion("1.0.*")]
29 | [assembly: AssemblyVersion("1.0.0.0")]
30 | [assembly: AssemblyFileVersion("1.0.0.0")]
31 |
32 | // Add some common permissions, these can be removed if not needed
33 | [assembly: UsesPermission(Android.Manifest.Permission.Internet)]
34 | [assembly: UsesPermission(Android.Manifest.Permission.WriteExternalStorage)]
35 |
--------------------------------------------------------------------------------
/frontend/BirdAtlas.Android/Resources/AboutResources.txt:
--------------------------------------------------------------------------------
1 | Images, layout descriptions, binary blobs and string dictionaries can be included
2 | in your application as resource files. Various Android APIs are designed to
3 | operate on the resource IDs instead of dealing with images, strings or binary blobs
4 | directly.
5 |
6 | For example, a sample Android app that contains a user interface layout (main.xml),
7 | an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png)
8 | would keep its resources in the "Resources" directory of the application:
9 |
10 | Resources/
11 | drawable-hdpi/
12 | icon.png
13 |
14 | drawable-ldpi/
15 | icon.png
16 |
17 | drawable-mdpi/
18 | icon.png
19 |
20 | layout/
21 | main.xml
22 |
23 | values/
24 | strings.xml
25 |
26 | In order to get the build system to recognize Android resources, set the build action to
27 | "AndroidResource". The native Android APIs do not operate directly with filenames, but
28 | instead operate on resource IDs. When you compile an Android application that uses resources,
29 | the build system will package the resources for distribution and generate a class called
30 | "Resource" that contains the tokens for each one of the resources included. For example,
31 | for the above Resources layout, this is what the Resource class would expose:
32 |
33 | public class Resource {
34 | public class drawable {
35 | public const int icon = 0x123;
36 | }
37 |
38 | public class layout {
39 | public const int main = 0x456;
40 | }
41 |
42 | public class strings {
43 | public const int first_string = 0xabc;
44 | public const int second_string = 0xbcd;
45 | }
46 | }
47 |
48 | You would then use R.drawable.icon to reference the drawable/icon.png file, or Resource.layout.main
49 | to reference the layout/main.xml file, or Resource.strings.first_string to reference the first
50 | string in the dictionary file values/strings.xml.
51 |
--------------------------------------------------------------------------------
/frontend/BirdAtlas.Android/Resources/layout/Tabbar.axml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/frontend/BirdAtlas.Android/Resources/layout/Toolbar.axml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/frontend/BirdAtlas.Android/Resources/mipmap-anydpi-v26/icon.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/frontend/BirdAtlas.Android/Resources/mipmap-anydpi-v26/icon_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/frontend/BirdAtlas.Android/Resources/mipmap-hdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend/BirdAtlas.Android/Resources/mipmap-hdpi/icon.png
--------------------------------------------------------------------------------
/frontend/BirdAtlas.Android/Resources/mipmap-hdpi/launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend/BirdAtlas.Android/Resources/mipmap-hdpi/launcher_foreground.png
--------------------------------------------------------------------------------
/frontend/BirdAtlas.Android/Resources/mipmap-mdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend/BirdAtlas.Android/Resources/mipmap-mdpi/icon.png
--------------------------------------------------------------------------------
/frontend/BirdAtlas.Android/Resources/mipmap-mdpi/launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend/BirdAtlas.Android/Resources/mipmap-mdpi/launcher_foreground.png
--------------------------------------------------------------------------------
/frontend/BirdAtlas.Android/Resources/mipmap-xhdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend/BirdAtlas.Android/Resources/mipmap-xhdpi/icon.png
--------------------------------------------------------------------------------
/frontend/BirdAtlas.Android/Resources/mipmap-xhdpi/launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend/BirdAtlas.Android/Resources/mipmap-xhdpi/launcher_foreground.png
--------------------------------------------------------------------------------
/frontend/BirdAtlas.Android/Resources/mipmap-xxhdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend/BirdAtlas.Android/Resources/mipmap-xxhdpi/icon.png
--------------------------------------------------------------------------------
/frontend/BirdAtlas.Android/Resources/mipmap-xxhdpi/launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend/BirdAtlas.Android/Resources/mipmap-xxhdpi/launcher_foreground.png
--------------------------------------------------------------------------------
/frontend/BirdAtlas.Android/Resources/mipmap-xxxhdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend/BirdAtlas.Android/Resources/mipmap-xxxhdpi/icon.png
--------------------------------------------------------------------------------
/frontend/BirdAtlas.Android/Resources/mipmap-xxxhdpi/launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend/BirdAtlas.Android/Resources/mipmap-xxxhdpi/launcher_foreground.png
--------------------------------------------------------------------------------
/frontend/BirdAtlas.Android/Resources/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FFFFFF
4 | #3F51B5
5 | #303F9F
6 | #FF4081
7 |
--------------------------------------------------------------------------------
/frontend/BirdAtlas.Android/Resources/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
24 |
27 |
--------------------------------------------------------------------------------
/frontend/BirdAtlas.iOS/AppDelegate.cs:
--------------------------------------------------------------------------------
1 | using Foundation;
2 | using Sharpnado.HorizontalListView;
3 | using UIKit;
4 | using Xamarin.Forms;
5 |
6 | namespace BirdAtlas.iOS
7 | {
8 | // The UIApplicationDelegate for the application. This class is responsible for launching the
9 | // User Interface of the application, as well as listening (and optionally responding) to
10 | // application events from iOS.
11 | [Register("AppDelegate")]
12 | public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
13 | {
14 | //
15 | // This method is invoked when the application has loaded and is ready to run. In this
16 | // method you should instantiate the window, load the UI into it and then make the window
17 | // visible.
18 | //
19 | // You have 17 seconds to return from this method, or iOS will terminate your application.
20 | //
21 | public override bool FinishedLaunching(UIApplication app, NSDictionary options)
22 | {
23 | Forms.SetFlags("CollectionView_Experimental");
24 | global::Xamarin.Forms.Forms.Init();
25 |
26 | Sharpnado.HorizontalListView.iOS.SharpnadoInitializer.Initialize();
27 | Sharpnado.Tabs.iOS.Preserver.Preserve();
28 |
29 | LoadApplication(new App());
30 |
31 | return base.FinishedLaunching(app, options);
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/frontend/BirdAtlas.iOS/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images": [
3 | {
4 | "scale": "2x",
5 | "size": "20x20",
6 | "idiom": "iphone",
7 | "filename": "Icon40.png"
8 | },
9 | {
10 | "scale": "3x",
11 | "size": "20x20",
12 | "idiom": "iphone",
13 | "filename": "Icon60.png"
14 | },
15 | {
16 | "scale": "2x",
17 | "size": "29x29",
18 | "idiom": "iphone",
19 | "filename": "Icon58.png"
20 | },
21 | {
22 | "scale": "3x",
23 | "size": "29x29",
24 | "idiom": "iphone",
25 | "filename": "Icon87.png"
26 | },
27 | {
28 | "scale": "2x",
29 | "size": "40x40",
30 | "idiom": "iphone",
31 | "filename": "Icon80.png"
32 | },
33 | {
34 | "scale": "3x",
35 | "size": "40x40",
36 | "idiom": "iphone",
37 | "filename": "Icon120.png"
38 | },
39 | {
40 | "scale": "2x",
41 | "size": "60x60",
42 | "idiom": "iphone",
43 | "filename": "Icon120.png"
44 | },
45 | {
46 | "scale": "3x",
47 | "size": "60x60",
48 | "idiom": "iphone",
49 | "filename": "Icon180.png"
50 | },
51 | {
52 | "scale": "1x",
53 | "size": "20x20",
54 | "idiom": "ipad",
55 | "filename": "Icon20.png"
56 | },
57 | {
58 | "scale": "2x",
59 | "size": "20x20",
60 | "idiom": "ipad",
61 | "filename": "Icon40.png"
62 | },
63 | {
64 | "scale": "1x",
65 | "size": "29x29",
66 | "idiom": "ipad",
67 | "filename": "Icon29.png"
68 | },
69 | {
70 | "scale": "2x",
71 | "size": "29x29",
72 | "idiom": "ipad",
73 | "filename": "Icon58.png"
74 | },
75 | {
76 | "scale": "1x",
77 | "size": "40x40",
78 | "idiom": "ipad",
79 | "filename": "Icon40.png"
80 | },
81 | {
82 | "scale": "2x",
83 | "size": "40x40",
84 | "idiom": "ipad",
85 | "filename": "Icon80.png"
86 | },
87 | {
88 | "scale": "1x",
89 | "size": "76x76",
90 | "idiom": "ipad",
91 | "filename": "Icon76.png"
92 | },
93 | {
94 | "scale": "2x",
95 | "size": "76x76",
96 | "idiom": "ipad",
97 | "filename": "Icon152.png"
98 | },
99 | {
100 | "scale": "2x",
101 | "size": "83.5x83.5",
102 | "idiom": "ipad",
103 | "filename": "Icon167.png"
104 | },
105 | {
106 | "scale": "1x",
107 | "size": "1024x1024",
108 | "idiom": "ios-marketing",
109 | "filename": "Icon1024.png"
110 | }
111 | ],
112 | "properties": {},
113 | "info": {
114 | "version": 1,
115 | "author": "xcode"
116 | }
117 | }
--------------------------------------------------------------------------------
/frontend/BirdAtlas.iOS/Assets.xcassets/AppIcon.appiconset/Icon1024.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend/BirdAtlas.iOS/Assets.xcassets/AppIcon.appiconset/Icon1024.png
--------------------------------------------------------------------------------
/frontend/BirdAtlas.iOS/Assets.xcassets/AppIcon.appiconset/Icon120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend/BirdAtlas.iOS/Assets.xcassets/AppIcon.appiconset/Icon120.png
--------------------------------------------------------------------------------
/frontend/BirdAtlas.iOS/Assets.xcassets/AppIcon.appiconset/Icon152.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend/BirdAtlas.iOS/Assets.xcassets/AppIcon.appiconset/Icon152.png
--------------------------------------------------------------------------------
/frontend/BirdAtlas.iOS/Assets.xcassets/AppIcon.appiconset/Icon167.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend/BirdAtlas.iOS/Assets.xcassets/AppIcon.appiconset/Icon167.png
--------------------------------------------------------------------------------
/frontend/BirdAtlas.iOS/Assets.xcassets/AppIcon.appiconset/Icon180.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend/BirdAtlas.iOS/Assets.xcassets/AppIcon.appiconset/Icon180.png
--------------------------------------------------------------------------------
/frontend/BirdAtlas.iOS/Assets.xcassets/AppIcon.appiconset/Icon20.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend/BirdAtlas.iOS/Assets.xcassets/AppIcon.appiconset/Icon20.png
--------------------------------------------------------------------------------
/frontend/BirdAtlas.iOS/Assets.xcassets/AppIcon.appiconset/Icon29.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend/BirdAtlas.iOS/Assets.xcassets/AppIcon.appiconset/Icon29.png
--------------------------------------------------------------------------------
/frontend/BirdAtlas.iOS/Assets.xcassets/AppIcon.appiconset/Icon40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend/BirdAtlas.iOS/Assets.xcassets/AppIcon.appiconset/Icon40.png
--------------------------------------------------------------------------------
/frontend/BirdAtlas.iOS/Assets.xcassets/AppIcon.appiconset/Icon58.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend/BirdAtlas.iOS/Assets.xcassets/AppIcon.appiconset/Icon58.png
--------------------------------------------------------------------------------
/frontend/BirdAtlas.iOS/Assets.xcassets/AppIcon.appiconset/Icon60.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend/BirdAtlas.iOS/Assets.xcassets/AppIcon.appiconset/Icon60.png
--------------------------------------------------------------------------------
/frontend/BirdAtlas.iOS/Assets.xcassets/AppIcon.appiconset/Icon76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend/BirdAtlas.iOS/Assets.xcassets/AppIcon.appiconset/Icon76.png
--------------------------------------------------------------------------------
/frontend/BirdAtlas.iOS/Assets.xcassets/AppIcon.appiconset/Icon80.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend/BirdAtlas.iOS/Assets.xcassets/AppIcon.appiconset/Icon80.png
--------------------------------------------------------------------------------
/frontend/BirdAtlas.iOS/Assets.xcassets/AppIcon.appiconset/Icon87.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend/BirdAtlas.iOS/Assets.xcassets/AppIcon.appiconset/Icon87.png
--------------------------------------------------------------------------------
/frontend/BirdAtlas.iOS/Entitlements.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/frontend/BirdAtlas.iOS/Framework/DeviceInfo.cs:
--------------------------------------------------------------------------------
1 | using BirdAtlas.Framework;
2 | using BirdAtlas.iOS.Framework;
3 | using UIKit;
4 | using Xamarin.Forms;
5 |
6 | [assembly: Dependency(typeof(DeviceInfo))]
7 | namespace BirdAtlas.iOS.Framework
8 | {
9 | public class DeviceInfo : IDeviceInfo
10 | {
11 | public float StatusbarHeight => (float)UIApplication.SharedApplication.StatusBarFrame.Size.Height;
12 | }
13 | }
--------------------------------------------------------------------------------
/frontend/BirdAtlas.iOS/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | UIDeviceFamily
6 |
7 | 1
8 | 2
9 |
10 | UISupportedInterfaceOrientations
11 |
12 | UIInterfaceOrientationPortrait
13 | UIInterfaceOrientationLandscapeLeft
14 | UIInterfaceOrientationLandscapeRight
15 |
16 | UISupportedInterfaceOrientations~ipad
17 |
18 | UIInterfaceOrientationPortrait
19 | UIInterfaceOrientationPortraitUpsideDown
20 | UIInterfaceOrientationLandscapeLeft
21 | UIInterfaceOrientationLandscapeRight
22 |
23 | MinimumOSVersion
24 | 8.0
25 | CFBundleDisplayName
26 | BirdAtlas
27 | CFBundleIdentifier
28 | com.companyname.BirdAtlas
29 | CFBundleVersion
30 | 1.0
31 | UILaunchStoryboardName
32 | LaunchScreen
33 | CFBundleName
34 | BirdAtlas
35 | XSAppIconAssets
36 | Assets.xcassets/AppIcon.appiconset
37 | UIAppFonts
38 |
39 | materialdesignicons-webfont.ttf
40 | Montserrat-Medium.ttf
41 | Montserrat-SemiBold.ttf
42 | Montserrat-Regular.ttf
43 | Montserrat-Light.ttf
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/frontend/BirdAtlas.iOS/Main.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 |
5 | using Foundation;
6 | using UIKit;
7 |
8 | namespace BirdAtlas.iOS
9 | {
10 | public class Application
11 | {
12 | // This is the main entry point of the application.
13 | static void Main(string[] args)
14 | {
15 | // if you want to use a different Application Delegate class from "AppDelegate"
16 | // you can specify it here.
17 | UIApplication.Main(args, null, "AppDelegate");
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/frontend/BirdAtlas.iOS/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("BirdAtlas.iOS")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("BirdAtlas.iOS")]
13 | [assembly: AssemblyCopyright("Copyright © 2014")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("72bdc44f-c588-44f3-b6df-9aace7daafdd")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/frontend/BirdAtlas.iOS/Resources/Default-568h@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend/BirdAtlas.iOS/Resources/Default-568h@2x.png
--------------------------------------------------------------------------------
/frontend/BirdAtlas.iOS/Resources/Default-Portrait.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend/BirdAtlas.iOS/Resources/Default-Portrait.png
--------------------------------------------------------------------------------
/frontend/BirdAtlas.iOS/Resources/Default-Portrait@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend/BirdAtlas.iOS/Resources/Default-Portrait@2x.png
--------------------------------------------------------------------------------
/frontend/BirdAtlas.iOS/Resources/Default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend/BirdAtlas.iOS/Resources/Default.png
--------------------------------------------------------------------------------
/frontend/BirdAtlas.iOS/Resources/Default@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend/BirdAtlas.iOS/Resources/Default@2x.png
--------------------------------------------------------------------------------
/frontend/BirdAtlas.iOS/Resources/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 |
39 |
--------------------------------------------------------------------------------
/frontend/BirdAtlas.iOS/Resources/Montserrat-Light.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend/BirdAtlas.iOS/Resources/Montserrat-Light.ttf
--------------------------------------------------------------------------------
/frontend/BirdAtlas.iOS/Resources/Montserrat-Medium.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend/BirdAtlas.iOS/Resources/Montserrat-Medium.ttf
--------------------------------------------------------------------------------
/frontend/BirdAtlas.iOS/Resources/Montserrat-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend/BirdAtlas.iOS/Resources/Montserrat-Regular.ttf
--------------------------------------------------------------------------------
/frontend/BirdAtlas.iOS/Resources/Montserrat-SemiBold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend/BirdAtlas.iOS/Resources/Montserrat-SemiBold.ttf
--------------------------------------------------------------------------------
/frontend/BirdAtlas.iOS/Resources/ic_bookmarks.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend/BirdAtlas.iOS/Resources/ic_bookmarks.png
--------------------------------------------------------------------------------
/frontend/BirdAtlas.iOS/Resources/ic_bookmarks@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend/BirdAtlas.iOS/Resources/ic_bookmarks@2x.png
--------------------------------------------------------------------------------
/frontend/BirdAtlas.iOS/Resources/ic_bookmarks@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend/BirdAtlas.iOS/Resources/ic_bookmarks@3x.png
--------------------------------------------------------------------------------
/frontend/BirdAtlas.iOS/Resources/ic_discover.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend/BirdAtlas.iOS/Resources/ic_discover.png
--------------------------------------------------------------------------------
/frontend/BirdAtlas.iOS/Resources/ic_discover@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend/BirdAtlas.iOS/Resources/ic_discover@2x.png
--------------------------------------------------------------------------------
/frontend/BirdAtlas.iOS/Resources/ic_discover@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend/BirdAtlas.iOS/Resources/ic_discover@3x.png
--------------------------------------------------------------------------------
/frontend/BirdAtlas.iOS/Resources/ic_search.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend/BirdAtlas.iOS/Resources/ic_search.png
--------------------------------------------------------------------------------
/frontend/BirdAtlas.iOS/Resources/ic_search@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend/BirdAtlas.iOS/Resources/ic_search@2x.png
--------------------------------------------------------------------------------
/frontend/BirdAtlas.iOS/Resources/ic_search@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend/BirdAtlas.iOS/Resources/ic_search@3x.png
--------------------------------------------------------------------------------
/frontend/BirdAtlas.iOS/Resources/materialdesignicons-webfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend/BirdAtlas.iOS/Resources/materialdesignicons-webfont.ttf
--------------------------------------------------------------------------------
/frontend/BirdAtlas.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BirdAtlas.Android", "BirdAtlas.Android\BirdAtlas.Android.csproj", "{59AE4C14-86B8-4C59-BBC2-C5F70ACF15CF}"
5 | EndProject
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BirdAtlas.iOS", "BirdAtlas.iOS\BirdAtlas.iOS.csproj", "{1866B926-D5BE-4248-9C4C-274B8F098D54}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BirdAtlas", "BirdAtlas\BirdAtlas.csproj", "{0100D27D-7213-4971-807D-130F269A7D67}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Release|Any CPU = Release|Any CPU
14 | Debug|iPhoneSimulator = Debug|iPhoneSimulator
15 | Release|iPhoneSimulator = Release|iPhoneSimulator
16 | Debug|iPhone = Debug|iPhone
17 | Release|iPhone = Release|iPhone
18 | Ad-Hoc|iPhone = Ad-Hoc|iPhone
19 | AppStore|iPhone = AppStore|iPhone
20 | EndGlobalSection
21 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
22 | {59AE4C14-86B8-4C59-BBC2-C5F70ACF15CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
23 | {59AE4C14-86B8-4C59-BBC2-C5F70ACF15CF}.Debug|Any CPU.Build.0 = Debug|Any CPU
24 | {59AE4C14-86B8-4C59-BBC2-C5F70ACF15CF}.Release|Any CPU.ActiveCfg = Release|Any CPU
25 | {59AE4C14-86B8-4C59-BBC2-C5F70ACF15CF}.Release|Any CPU.Build.0 = Release|Any CPU
26 | {59AE4C14-86B8-4C59-BBC2-C5F70ACF15CF}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
27 | {59AE4C14-86B8-4C59-BBC2-C5F70ACF15CF}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
28 | {59AE4C14-86B8-4C59-BBC2-C5F70ACF15CF}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
29 | {59AE4C14-86B8-4C59-BBC2-C5F70ACF15CF}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
30 | {59AE4C14-86B8-4C59-BBC2-C5F70ACF15CF}.Debug|iPhone.ActiveCfg = Debug|Any CPU
31 | {59AE4C14-86B8-4C59-BBC2-C5F70ACF15CF}.Debug|iPhone.Build.0 = Debug|Any CPU
32 | {59AE4C14-86B8-4C59-BBC2-C5F70ACF15CF}.Release|iPhone.ActiveCfg = Release|Any CPU
33 | {59AE4C14-86B8-4C59-BBC2-C5F70ACF15CF}.Release|iPhone.Build.0 = Release|Any CPU
34 | {59AE4C14-86B8-4C59-BBC2-C5F70ACF15CF}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
35 | {59AE4C14-86B8-4C59-BBC2-C5F70ACF15CF}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
36 | {59AE4C14-86B8-4C59-BBC2-C5F70ACF15CF}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
37 | {59AE4C14-86B8-4C59-BBC2-C5F70ACF15CF}.AppStore|iPhone.Build.0 = Debug|Any CPU
38 | {1866B926-D5BE-4248-9C4C-274B8F098D54}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator
39 | {1866B926-D5BE-4248-9C4C-274B8F098D54}.Debug|Any CPU.Build.0 = Debug|iPhoneSimulator
40 | {1866B926-D5BE-4248-9C4C-274B8F098D54}.Release|Any CPU.ActiveCfg = Release|iPhoneSimulator
41 | {1866B926-D5BE-4248-9C4C-274B8F098D54}.Release|Any CPU.Build.0 = Release|iPhoneSimulator
42 | {1866B926-D5BE-4248-9C4C-274B8F098D54}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
43 | {1866B926-D5BE-4248-9C4C-274B8F098D54}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
44 | {1866B926-D5BE-4248-9C4C-274B8F098D54}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
45 | {1866B926-D5BE-4248-9C4C-274B8F098D54}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
46 | {1866B926-D5BE-4248-9C4C-274B8F098D54}.Debug|iPhone.ActiveCfg = Debug|iPhone
47 | {1866B926-D5BE-4248-9C4C-274B8F098D54}.Debug|iPhone.Build.0 = Debug|iPhone
48 | {1866B926-D5BE-4248-9C4C-274B8F098D54}.Release|iPhone.ActiveCfg = Release|iPhone
49 | {1866B926-D5BE-4248-9C4C-274B8F098D54}.Release|iPhone.Build.0 = Release|iPhone
50 | {1866B926-D5BE-4248-9C4C-274B8F098D54}.Ad-Hoc|iPhone.ActiveCfg = Ad-Hoc|iPhone
51 | {1866B926-D5BE-4248-9C4C-274B8F098D54}.Ad-Hoc|iPhone.Build.0 = Ad-Hoc|iPhone
52 | {1866B926-D5BE-4248-9C4C-274B8F098D54}.AppStore|iPhone.ActiveCfg = AppStore|iPhone
53 | {1866B926-D5BE-4248-9C4C-274B8F098D54}.AppStore|iPhone.Build.0 = AppStore|iPhone
54 | {0100D27D-7213-4971-807D-130F269A7D67}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
55 | {0100D27D-7213-4971-807D-130F269A7D67}.Debug|Any CPU.Build.0 = Debug|Any CPU
56 | {0100D27D-7213-4971-807D-130F269A7D67}.Release|Any CPU.ActiveCfg = Release|Any CPU
57 | {0100D27D-7213-4971-807D-130F269A7D67}.Release|Any CPU.Build.0 = Release|Any CPU
58 | {0100D27D-7213-4971-807D-130F269A7D67}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
59 | {0100D27D-7213-4971-807D-130F269A7D67}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
60 | {0100D27D-7213-4971-807D-130F269A7D67}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
61 | {0100D27D-7213-4971-807D-130F269A7D67}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
62 | {0100D27D-7213-4971-807D-130F269A7D67}.Debug|iPhone.ActiveCfg = Debug|Any CPU
63 | {0100D27D-7213-4971-807D-130F269A7D67}.Debug|iPhone.Build.0 = Debug|Any CPU
64 | {0100D27D-7213-4971-807D-130F269A7D67}.Release|iPhone.ActiveCfg = Release|Any CPU
65 | {0100D27D-7213-4971-807D-130F269A7D67}.Release|iPhone.Build.0 = Release|Any CPU
66 | {0100D27D-7213-4971-807D-130F269A7D67}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
67 | {0100D27D-7213-4971-807D-130F269A7D67}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
68 | {0100D27D-7213-4971-807D-130F269A7D67}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
69 | {0100D27D-7213-4971-807D-130F269A7D67}.AppStore|iPhone.Build.0 = Debug|Any CPU
70 | EndGlobalSection
71 | EndGlobal
72 |
--------------------------------------------------------------------------------
/frontend/BirdAtlas/App.xaml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/frontend/BirdAtlas/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using BirdAtlas.Views;
2 | using Xamarin.Forms;
3 | using Xamarin.Forms.Xaml;
4 | using Prism;
5 | using Prism.DryIoc;
6 | using Prism.Ioc;
7 | using BirdAtlas.ViewModels;
8 | using BirdAtlas.Services;
9 |
10 | [assembly: XamlCompilation(XamlCompilationOptions.Compile)]
11 | namespace BirdAtlas
12 | {
13 | public partial class App : PrismApplication
14 | {
15 | public App() : this(null) { }
16 |
17 | public App(IPlatformInitializer platformInitializer) : base(platformInitializer)
18 | {
19 | }
20 |
21 | protected override async void OnInitialized()
22 | {
23 | InitializeComponent();
24 |
25 | Sharpnado.Tabs.Initializer.Initialize(false, false);
26 | Sharpnado.Shades.Initializer.Initialize(false);
27 | Sharpnado.HorizontalListView.Initializer.Initialize(false, false);
28 |
29 | await NavigationService.NavigateAsync("NavigationPage/StartPage");
30 | }
31 |
32 | protected override void RegisterTypes(IContainerRegistry containerRegistry)
33 | {
34 | containerRegistry.RegisterSingleton();
35 |
36 | containerRegistry.RegisterForNavigation();
37 | containerRegistry.RegisterForNavigation();
38 | containerRegistry.RegisterForNavigation();
39 | containerRegistry.RegisterForNavigation();
40 | containerRegistry.RegisterForNavigation();
41 | containerRegistry.RegisterForNavigation();
42 | }
43 | }
44 | }
--------------------------------------------------------------------------------
/frontend/BirdAtlas/Behaviors/EntranceBehavior.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading.Tasks;
3 | using Xamarin.Forms;
4 |
5 | namespace BirdAtlas.Behaviors
6 | {
7 | public class EntranceTransition : Behavior
8 | {
9 | const int Delay = 100;
10 | const int TranslateFrom = 6;
11 |
12 | private VisualElement _associatedObject;
13 |
14 | public static readonly BindableProperty DurationProperty =
15 | BindableProperty.Create(nameof(Duration), typeof(string), typeof(EntranceTransition), "500",
16 | BindingMode.TwoWay, null);
17 |
18 | public string Duration
19 | {
20 | get { return (string)GetValue(DurationProperty); }
21 | set { SetValue(DurationProperty, value); }
22 | }
23 |
24 | protected override void OnAttachedTo(VisualElement bindable)
25 | {
26 | base.OnAttachedTo(bindable);
27 | _associatedObject = bindable;
28 | _associatedObject.PropertyChanged += OnPropertyChanged;
29 | }
30 |
31 | protected override void OnDetachingFrom(VisualElement bindable)
32 | {
33 | StopAnimation();
34 | _associatedObject.PropertyChanged -= OnPropertyChanged;
35 | _associatedObject = null;
36 | base.OnDetachingFrom(bindable);
37 | }
38 |
39 | async void OnPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
40 | {
41 | if (e.PropertyName == "Renderer")
42 | await StartAnimationAsync();
43 | }
44 |
45 | void SetInitialTransitionState()
46 | {
47 | SetInitialTransitionState(_associatedObject);
48 | }
49 |
50 | void SetInitialTransitionState(VisualElement element)
51 | {
52 | element.Opacity = 0;
53 | element.TranslationX = _associatedObject.TranslationX + TranslateFrom;
54 | element.TranslationY = _associatedObject.TranslationY + TranslateFrom;
55 | }
56 |
57 | void StopAnimation()
58 | {
59 | ViewExtensions.CancelAnimations(_associatedObject);
60 | }
61 |
62 | async Task StartAnimationAsync()
63 | {
64 | StopAnimation();
65 | SetInitialTransitionState();
66 |
67 | //if (!HasParentEntranceTransition(_associatedObject))
68 | await AnimateItemAsync(_associatedObject);
69 | }
70 |
71 | async Task AnimateItemAsync(VisualElement element)
72 | {
73 | await Task.Delay(Delay);
74 |
75 | var parentAnimation = new Animation();
76 |
77 | var translateXAnimation = new Animation(v => element.TranslationX = v, element.TranslationX, 0, Easing.SpringIn);
78 | var translateYAnimation = new Animation(v => element.TranslationY = v, element.TranslationY, 0, Easing.SpringIn);
79 | var opacityAnimation = new Animation(v => element.Opacity = v, 0, 1, Easing.CubicIn);
80 |
81 | parentAnimation.Add(0, 0.75, translateXAnimation);
82 | parentAnimation.Add(0, 0.75, translateYAnimation);
83 | parentAnimation.Add(0, 1, opacityAnimation);
84 |
85 | parentAnimation.Commit(_associatedObject, "EntranceTransition" + element.Id, 16, Convert.ToUInt32(Duration), null, (v, c) => StopAnimation());
86 | }
87 |
88 | //bool HasParentEntranceTransition(VisualElement element)
89 | //{
90 | // VisualElement parent = VisualTreeHelper.GetParent(element);
91 | // var behaviors = parent.Behaviors;
92 | // return behaviors.OfType().FirstOrDefault() != null;
93 | //}
94 | }
95 | }
--------------------------------------------------------------------------------
/frontend/BirdAtlas/BirdAtlas.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.0
5 |
6 |
7 |
8 | pdbonly
9 | true
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 |
39 |
40 |
--------------------------------------------------------------------------------
/frontend/BirdAtlas/Converters/HabitatTypeToColorConverter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Globalization;
3 | using BirdAtlas.Models;
4 | using Xamarin.Forms;
5 |
6 | namespace BirdAtlas.Converters
7 | {
8 | public class HabitatTypeToColorConverter : IValueConverter
9 | {
10 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
11 | {
12 | if(value is HabitatType habitatType)
13 | {
14 | switch(habitatType)
15 | {
16 | case HabitatType.Tundra:
17 | case HabitatType.Grassland:
18 | return (Color)Application.Current.Resources["WarmBlue"];
19 | case HabitatType.Forest:
20 | case HabitatType.Wetland:
21 | case HabitatType.UrbanSuburban:
22 | return (Color)Application.Current.Resources["LightBlue"];
23 | case HabitatType.Desert:
24 | case HabitatType.Ocean:
25 | return (Color)Application.Current.Resources["DarkBlue"];
26 | }
27 | }
28 |
29 | return Color.Default;
30 | }
31 |
32 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
33 | {
34 | throw new NotImplementedException();
35 | }
36 | }
37 | }
--------------------------------------------------------------------------------
/frontend/BirdAtlas/Extensions/IEnumerableExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 |
5 | namespace BirdAtlas.Extensions
6 | {
7 | public static class EnumerableExtensions
8 | {
9 | public static IEnumerable Shuffle(this IEnumerable source)
10 | {
11 | return source.Shuffle(new Random());
12 | }
13 |
14 | public static IEnumerable Shuffle(this IEnumerable source, Random rng)
15 | {
16 | if (source == null) throw new ArgumentNullException("source");
17 | if (rng == null) throw new ArgumentNullException("rng");
18 |
19 | return source.ShuffleIterator(rng);
20 | }
21 |
22 | private static IEnumerable ShuffleIterator(this IEnumerable source, Random rng)
23 | {
24 | var buffer = source.ToList();
25 | for (int i = 0; i < buffer.Count; i++)
26 | {
27 | int j = rng.Next(i, buffer.Count);
28 | yield return buffer[j];
29 |
30 | buffer[j] = buffer[i];
31 | }
32 | }
33 | }
34 | }
--------------------------------------------------------------------------------
/frontend/BirdAtlas/Framework/IDeviceInfo.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace BirdAtlas.Framework
4 | {
5 | public interface IDeviceInfo
6 | {
7 | float StatusbarHeight { get; }
8 | }
9 | }
--------------------------------------------------------------------------------
/frontend/BirdAtlas/Models/Enums.cs:
--------------------------------------------------------------------------------
1 | namespace BirdAtlas.Models
2 | {
3 | public enum PageMode
4 | {
5 | None,
6 | Menu,
7 | Navigate,
8 | Modal
9 | }
10 |
11 | public enum PageAction
12 | {
13 | None,
14 | Settings
15 | }
16 |
17 | public enum HabitatType
18 | {
19 | Forest,
20 | Grassland,
21 | Tundra,
22 | Desert,
23 | Wetland,
24 | Ocean,
25 | UrbanSuburban
26 | }
27 | }
--------------------------------------------------------------------------------
/frontend/BirdAtlas/Models/Habitat.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace BirdAtlas.Models
4 | {
5 | public class Habitat
6 | {
7 | public string Name { get; set; }
8 | public HabitatType Type { get; set; }
9 | public int Amount { get; set; }
10 | }
11 | }
--------------------------------------------------------------------------------
/frontend/BirdAtlas/Models/Nearby.cs:
--------------------------------------------------------------------------------
1 | namespace BirdAtlas.Models
2 | {
3 | public class Nearby
4 | {
5 | public string ImageUrl { get; set; }
6 | public string Name { get; set; }
7 | }
8 | }
--------------------------------------------------------------------------------
/frontend/BirdAtlas/Models/Story.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace BirdAtlas.Models
4 | {
5 | public class Story
6 | {
7 | public Guid ID { get; set; }
8 | public string ImageUrl { get; set; }
9 | public string Category { get; set; }
10 | public string Title { get; set; }
11 | public bool IsFeatured { get; set; }
12 | public DateTime PublishedOn { get; set; }
13 | public string Author { get; set; }
14 | public string Content { get; set; }
15 | }
16 | }
--------------------------------------------------------------------------------
/frontend/BirdAtlas/Services/BirdAtlasMockAPI.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using BirdAtlas.Extensions;
6 | using BirdAtlas.Models;
7 |
8 | namespace BirdAtlas.Services
9 | {
10 | public class BirdAtlasMockAPI : IBirdAtlasAPI
11 | {
12 | private List _stories = new List();
13 |
14 | public BirdAtlasMockAPI()
15 | {
16 | InitStories();
17 | }
18 |
19 | public Task> GetHabitatsAsync()
20 | {
21 | return null;
22 | }
23 |
24 | public Task> GetNearbiesAsync()
25 | {
26 | return null;
27 | }
28 |
29 | public Task GetStoryAsync(Guid id)
30 | {
31 | return Task.FromResult(_stories.FirstOrDefault(i => i.ID == id));
32 | }
33 |
34 | public Task> GetStoriesAsync()
35 | {
36 | return Task.FromResult>(_stories);
37 | }
38 |
39 | public Task> GetFeaturedStories(int amount)
40 | {
41 | amount = amount > _stories.Count ? _stories.Count : amount;
42 | return Task.FromResult>(_stories.Shuffle().Take(amount));
43 | }
44 |
45 | public Task> GetNewestStories(int amount)
46 | {
47 | amount = amount > _stories.Count ? _stories.Count : amount;
48 | return Task.FromResult>(_stories.OrderByDescending(story => story.PublishedOn).Take(amount));
49 | }
50 |
51 | private void InitStories()
52 | {
53 | //https://stackoverflow.com/questions/41160918/xamarin-forms-image-source-with-ssl
54 | _stories.Add(new Story() { ID = Guid.NewGuid(), IsFeatured = true, PublishedOn = DateTime.Now, Author = "Menno Schilthuizen", Category = "The Wilds", Title = "Why we need to save the scavengers?", ImageUrl = "http://www.birdlife.org/sites/default/files/styles/slider_image/public/slider/arcticternb1_markus_varesvuo-2.jpg" });
55 | _stories.Add(new Story() { ID = Guid.NewGuid(), IsFeatured = false, PublishedOn = DateTime.Now.AddDays(-1), Author = "Menno Schilthuizen", Category = "Science", Title = "Drunk birds? What is happening...", ImageUrl = "http://www.birdlife.org/sites/default/files/styles/full_620x295/public/news/little_spiderhunter_c_noicherrybeans_shutterstock_smaller_1.jpg" });
56 | _stories.Add(new Story() { ID = Guid.NewGuid(), IsFeatured = true, PublishedOn = DateTime.Now.AddDays(-2), Author = "Menno Schilthuizen", Category = "The Wilds", Title = "Why we need to save the scavengers?", ImageUrl = "http://www.birdlife.org/sites/default/files/styles/full_620x295/public/news/canada_warbler_c_jayne_gulbrand_smaller.jpg" });
57 | _stories.Add(new Story() { ID = Guid.NewGuid(), IsFeatured = true, PublishedOn = DateTime.Now.AddDays(-3), Author = "Menno Schilthuizen", Category = "Science", Title = "Drunk birds? What is happening...", ImageUrl = "http://cdn.images.express.co.uk/img/dynamic/13/590x/549233_1.jpg" });
58 | _stories.Add(new Story() { ID = Guid.NewGuid(), IsFeatured = true, PublishedOn = DateTime.Now.AddDays(-4), Author = "Menno Schilthuizen", Category = "The Wilds", Title = "Why we need to save the scavengers?", ImageUrl = "http://www.birdlife.org/sites/default/files/styles/full_620x295/public/news/rufous_hummingbird_selasphorus_rufus_c_ryan_bushby_1.jpg" });
59 | _stories.Add(new Story() { ID = Guid.NewGuid(), IsFeatured = false, PublishedOn = DateTime.Now.AddDays(-5), Author = "Menno Schilthuizen", Category = "Science", Title = "Drunk birds? What is happening...", ImageUrl = "http://www.birdlife.org/sites/default/files/styles/third_thumbnail_360x170/public/news/blossomcrown_c_martin_mecnarowski_shutterstock_2.jpg" });
60 |
61 | foreach (var story in _stories)
62 | story.Content = "A crumbling concrete wall, a ramp and a vast expanse of asphalt on which identical silvery-grey sedans are slowly circling and zigzagging between traffic cones. It does not seem like much but, to urban biologists, the Kadan driving school in the Japanese city of Sendai is hallowed ground. The four of us (the biology students Minoru Chiba and Yawara Takeda, the biologist Iva Njunjić, and I) have been sitting on that crumbling wall for several hours now, hoping to observe what this place is famous for.\r\n\r\nIt was here that, in 1975, the local carrion crows (Corvus corone) discovered how to use cars as nutcrackers. The crows have a predilection for the Japanese walnut (Juglans ailantifolia) that grows abundantly in the city. The pretty nuts (a bit smaller than commercial walnuts";
63 | }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/frontend/BirdAtlas/Services/IBirdAtlasAPI.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Threading.Tasks;
4 | using BirdAtlas.Models;
5 |
6 | namespace BirdAtlas.Services
7 | {
8 | public interface IBirdAtlasAPI
9 | {
10 | Task GetStoryAsync(Guid id);
11 | Task> GetStoriesAsync();
12 | Task> GetHabitatsAsync();
13 | Task> GetNearbiesAsync();
14 |
15 | Task> GetFeaturedStories(int amount);
16 | Task> GetNewestStories(int amount);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/frontend/BirdAtlas/ViewModels/BaseViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading.Tasks;
3 | using BirdAtlas.Services;
4 | using BirdAtlas.Views;
5 | using Prism.Commands;
6 | using Prism.Mvvm;
7 | using Prism.Navigation;
8 |
9 | namespace BirdAtlas.ViewModels
10 | {
11 | public class BaseViewModel : BindableBase, INavigationAware, IInitializeAsync
12 | {
13 | protected INavigationService NavigationService { get; private set; }
14 | protected IBirdAtlasAPI BirdAtlasAPI { get; private set; }
15 |
16 | private DelegateCommand _navigateBackCommand;
17 | public DelegateCommand NavigateBackCommand => _navigateBackCommand ?? (_navigateBackCommand = new DelegateCommand(async () => await NavigationService.GoBackAsync()));
18 |
19 | private DelegateCommand _settingsCommand;
20 | public DelegateCommand SettingsCommand => _settingsCommand ?? (_settingsCommand = new DelegateCommand(async () => await NavigationService.NavigateAsync("SettingsPage")));
21 |
22 | public BaseViewModel(IBirdAtlasAPI birdAtlasAPI, INavigationService navigationService)
23 | {
24 | BirdAtlasAPI = birdAtlasAPI;
25 | NavigationService = navigationService;
26 | }
27 |
28 | public void OnNavigatedFrom(INavigationParameters parameters)
29 | {
30 | }
31 |
32 | public virtual void OnNavigatedTo(INavigationParameters parameters)
33 | {
34 | }
35 |
36 | public void OnNavigatingTo(INavigationParameters parameters)
37 | {
38 | }
39 |
40 | public virtual async Task InitializeAsync(INavigationParameters parameters)
41 | {
42 | }
43 | }
44 | }
--------------------------------------------------------------------------------
/frontend/BirdAtlas/ViewModels/BookmarkViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using BirdAtlas.Services;
3 | using Prism.Navigation;
4 |
5 | namespace BirdAtlas.ViewModels
6 | {
7 | public class BookmarkViewModel : BaseViewModel
8 | {
9 | public BookmarkViewModel(IBirdAtlasAPI birdAtlasAPI, INavigationService navigationService) : base(birdAtlasAPI, navigationService)
10 | {
11 | }
12 | }
13 | }
--------------------------------------------------------------------------------
/frontend/BirdAtlas/ViewModels/DiscoverViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Collections.ObjectModel;
4 | using System.Threading.Tasks;
5 | using BirdAtlas.Models;
6 | using BirdAtlas.Services;
7 | using BirdAtlas.Views;
8 | using Prism.Commands;
9 | using Prism.Navigation;
10 |
11 | namespace BirdAtlas.ViewModels
12 | {
13 | public class DiscoverViewModel : BaseViewModel
14 | {
15 | private ObservableCollection _stories = new ObservableCollection();
16 | public ObservableCollection Stories
17 | {
18 | get => _stories;
19 | set => SetProperty(ref _stories, value);
20 | }
21 |
22 | private ObservableCollection _habitats = new ObservableCollection();
23 | public ObservableCollection Habitats
24 | {
25 | get => _habitats;
26 | set => SetProperty(ref _habitats, value);
27 | }
28 |
29 | private ObservableCollection _nearbyBirds = new ObservableCollection();
30 | public ObservableCollection NearbyBirds
31 | {
32 | get => _nearbyBirds;
33 | set => SetProperty(ref _nearbyBirds, value);
34 | }
35 |
36 | private DelegateCommand _storiesTappedCommand;
37 | public DelegateCommand StoriesTappedCommand => _storiesTappedCommand ?? (_storiesTappedCommand = new DelegateCommand(async () => await NavigationService.NavigateAsync(nameof(StoryOverviewPage))));
38 |
39 | private DelegateCommand _storyTappedCommand;
40 | public DelegateCommand StoryTappedCommand => _storyTappedCommand ?? (_storyTappedCommand = new DelegateCommand(async story => await NavigationService.NavigateAsync($"{nameof(StoryDetailPage)}?id={story.ID.ToString()}")));
41 |
42 | public DiscoverViewModel(IBirdAtlasAPI birdAtlasAPI, INavigationService navigationService) : base(birdAtlasAPI, navigationService)
43 | {
44 | Habitats.Add(new Habitat() { Name = "Forests", Type = HabitatType.Forest, Amount = 290 });
45 | Habitats.Add(new Habitat() { Name = "Tundra", Type = HabitatType.Tundra, Amount = 311 });
46 | Habitats.Add(new Habitat() { Name = "Deserts", Type = HabitatType.Desert, Amount = 307 });
47 |
48 | NearbyBirds.Add(new Nearby() { Name = "Eurasian hoopoe", ImageUrl = "http://www.birdlife.org/sites/default/files/styles/third_thumbnail_360x170/public/news/canada_warbler_borb_c_steve_jones.jpg" });
49 | NearbyBirds.Add(new Nearby() { Name = "Short-eared owl", ImageUrl = "http://www.birdlife.org/sites/default/files/styles/third_thumbnail_360x170/public/news/black-breasted_puffleg_branch_c_murray_cooper_1.jpg" });
50 | NearbyBirds.Add(new Nearby() { Name = "Raven", ImageUrl = "http://www.birdlife.org/sites/default/files/styles/third_thumbnail_360x170/public/news/marsh_antwren_c_marco_silva.jpg" });
51 | NearbyBirds.Add(new Nearby() { Name = "Pigeon", ImageUrl = "http://www.birdlife.org/sites/default/files/styles/third_thumbnail_360x170/public/Fujingaho_Magazine/Fujingaho202001/fg2002_jpgjing_sayan_fg2001_taka_01_01.jpg" });
52 | }
53 | }
54 | }
--------------------------------------------------------------------------------
/frontend/BirdAtlas/ViewModels/SearchViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using BirdAtlas.Services;
3 | using Prism.Navigation;
4 |
5 | namespace BirdAtlas.ViewModels
6 | {
7 | public class SearchViewModel : BaseViewModel
8 | {
9 | public SearchViewModel(IBirdAtlasAPI birdAtlasAPI, INavigationService navigationService) : base(birdAtlasAPI, navigationService)
10 | {
11 | }
12 | }
13 | }
--------------------------------------------------------------------------------
/frontend/BirdAtlas/ViewModels/SettingsViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using BirdAtlas.Services;
3 | using Prism.Navigation;
4 |
5 | namespace BirdAtlas.ViewModels
6 | {
7 | public class SettingsViewModel : BaseViewModel
8 | {
9 | public SettingsViewModel(IBirdAtlasAPI birdAtlasAPI, INavigationService navigationService) : base(birdAtlasAPI, navigationService)
10 | {
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/frontend/BirdAtlas/ViewModels/StartViewModel.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Collections.ObjectModel;
3 | using System.Threading.Tasks;
4 | using BirdAtlas.Models;
5 | using BirdAtlas.Services;
6 | using Prism.Navigation;
7 |
8 | namespace BirdAtlas.ViewModels
9 | {
10 | public class StartViewModel : BaseViewModel
11 | {
12 | bool _loaded = false;
13 |
14 | private int _selectedViewModelIndex = 0;
15 | public int SelectedViewModelIndex
16 | {
17 | get => _selectedViewModelIndex;
18 | set => SetProperty(ref _selectedViewModelIndex, value);
19 | }
20 |
21 | public DiscoverViewModel DiscoverViewModel { get; }
22 | public SearchViewModel SearchViewModel { get; }
23 | public BookmarkViewModel BookmarkViewModel { get; }
24 |
25 | public StartViewModel(IBirdAtlasAPI birdAtlasAPI, INavigationService navigationService) : base(birdAtlasAPI, navigationService)
26 | {
27 | DiscoverViewModel = new DiscoverViewModel(BirdAtlasAPI, NavigationService);
28 | SearchViewModel = new SearchViewModel(BirdAtlasAPI, NavigationService);
29 | BookmarkViewModel = new BookmarkViewModel(BirdAtlasAPI, NavigationService);
30 | }
31 |
32 | public async override void OnNavigatedTo(INavigationParameters parameters)
33 | {
34 | if (!_loaded)
35 | {
36 | await Task.WhenAll(new List()
37 | {
38 | { Task.Run(() => GetStoriesAsync()) }
39 | //, { Task.Run(() => BirdAtlasAPI.GetHabitatsAsync()) }
40 | //, { Task.Run(() => BirdAtlasAPI.GetNearbiesAsync()) }
41 | });
42 | _loaded = true;
43 | }
44 | }
45 |
46 | private async Task GetStoriesAsync()
47 | {
48 | var stories = await BirdAtlasAPI.GetStoriesAsync();
49 | App.Current.Dispatcher.BeginInvokeOnMainThread(() => DiscoverViewModel.Stories = new ObservableCollection(stories));
50 | //foreach (var story in stories)
51 | // App.Current.Dispatcher.BeginInvokeOnMainThread(() => DiscoverViewModel.Stories.Add(story));
52 | }
53 | }
54 | }
--------------------------------------------------------------------------------
/frontend/BirdAtlas/ViewModels/StoryDetailViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using BirdAtlas.Models;
3 | using BirdAtlas.Services;
4 | using Prism.Navigation;
5 |
6 | namespace BirdAtlas.ViewModels
7 | {
8 | public class StoryDetailViewModel : BaseViewModel
9 | {
10 | private Story _story;
11 | public Story Story
12 | {
13 | get => _story;
14 | set => SetProperty(ref _story, value);
15 | }
16 |
17 | public StoryDetailViewModel(IBirdAtlasAPI birdAtlasAPI, INavigationService navigationService) : base(birdAtlasAPI, navigationService)
18 | {
19 | }
20 |
21 | public async override void OnNavigatedTo(INavigationParameters parameters)
22 | {
23 | string stringID = parameters["id"] as string;
24 |
25 | if (!string.IsNullOrEmpty(stringID) && Guid.Parse(stringID) is Guid id)
26 | Story = await BirdAtlasAPI.GetStoryAsync(id);
27 | }
28 | }
29 | }
--------------------------------------------------------------------------------
/frontend/BirdAtlas/ViewModels/StoryOverviewViewModel.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Collections.ObjectModel;
3 | using System.Threading.Tasks;
4 | using BirdAtlas.Models;
5 | using BirdAtlas.Services;
6 | using BirdAtlas.Views;
7 | using Prism.Commands;
8 | using Prism.Navigation;
9 |
10 | namespace BirdAtlas.ViewModels
11 | {
12 | public class StoryOverviewViewModel : BaseViewModel
13 | {
14 | private bool _loaded = false;
15 |
16 | private ObservableCollection _featuredStories = new ObservableCollection();
17 | public ObservableCollection FeaturedStories
18 | {
19 | get => _featuredStories;
20 | set => SetProperty(ref _featuredStories, value);
21 | }
22 |
23 | private ObservableCollection _newStories = new ObservableCollection();
24 | public ObservableCollection NewStories
25 | {
26 | get => _newStories;
27 | set => SetProperty(ref _newStories, value);
28 | }
29 |
30 | private DelegateCommand _storyItemTappedCommand;
31 | public DelegateCommand StoryItemTappedCommand => _storyItemTappedCommand ?? (_storyItemTappedCommand = new DelegateCommand(async story => await NavigationService.NavigateAsync($"{nameof(StoryDetailPage)}?id={story.ID}")));
32 |
33 | public StoryOverviewViewModel(IBirdAtlasAPI birdAtlasAPI, INavigationService navigationService) : base(birdAtlasAPI, navigationService)
34 | {
35 | }
36 |
37 | public override async Task InitializeAsync(INavigationParameters parameters)
38 | {
39 | await Task.WhenAll(new List()
40 | {
41 | { Task.Run(() => GetFeaturedStoriesAsync()) }
42 | , { Task.Run(() => GetNewestStoriesAsync()) }
43 | });
44 | }
45 |
46 | private async Task GetFeaturedStoriesAsync()
47 | {
48 | var featuredStories = await BirdAtlasAPI.GetFeaturedStories(3);
49 | App.Current.Dispatcher.BeginInvokeOnMainThread(() => FeaturedStories = new ObservableCollection(featuredStories));
50 | //foreach (var story in featuredStories)
51 | // App.Current.Dispatcher.BeginInvokeOnMainThread(() => FeaturedStories.Add(story));
52 | }
53 |
54 | private async Task GetNewestStoriesAsync()
55 | {
56 | var newStories = await BirdAtlasAPI.GetNewestStories(5);
57 | App.Current.Dispatcher.BeginInvokeOnMainThread(() => NewStories = new ObservableCollection(newStories));
58 | //foreach (var story in newStories)
59 | // App.Current.Dispatcher.BeginInvokeOnMainThread(() => NewStories.Add(story));
60 | }
61 | }
62 | }
--------------------------------------------------------------------------------
/frontend/BirdAtlas/Views/BasePage.xaml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
29 |
30 |
37 |
38 |
43 |
44 |
45 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/frontend/BirdAtlas/Views/BasePage.xaml.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using BirdAtlas.Framework;
3 | using BirdAtlas.Models;
4 | using Xamarin.Forms;
5 |
6 | namespace BirdAtlas.Views
7 | {
8 | public partial class BasePage : ContentPage
9 | {
10 | public IList BasePageContent => BaseContentGrid.Children;
11 |
12 | #region Bindable properties
13 | public static readonly BindableProperty BasePageTitleProperty =
14 | BindableProperty.Create(nameof(BasePageTitle), typeof(string), typeof(BasePage), string.Empty, defaultBindingMode: BindingMode.OneWay, propertyChanged: OnBasePageTitleChanged);
15 |
16 | public static readonly BindableProperty PageModeProperty =
17 | BindableProperty.Create(nameof(PageMode), typeof(PageMode), typeof(BasePage), PageMode.None, propertyChanged: OnPageModePropertyChanged);
18 |
19 | public static readonly BindableProperty PageActionProperty =
20 | BindableProperty.Create(nameof(PageAction), typeof(PageAction), typeof(BasePage), PageAction.None, propertyChanged: OnPageActionPropertyChanged);
21 |
22 | public string BasePageTitle
23 | {
24 | get => (string)GetValue(BasePageTitleProperty);
25 | set => SetValue(BasePageTitleProperty, value);
26 | }
27 |
28 | public PageMode PageMode
29 | {
30 | get => (PageMode)GetValue(PageModeProperty);
31 | set => SetValue(PageModeProperty, value);
32 | }
33 |
34 | public PageAction PageAction
35 | {
36 | get => (PageAction)GetValue(PageActionProperty);
37 | set => SetValue(PageActionProperty, value);
38 | }
39 |
40 | private static void OnBasePageTitleChanged(BindableObject bindable, object oldValue, object newValue)
41 | {
42 | if (bindable != null && bindable is BasePage basePage)
43 | basePage.TitleLabel.Text = (string)newValue;
44 | }
45 |
46 | private static void OnPageModePropertyChanged(BindableObject bindable, object oldValue, object newValue)
47 | {
48 | if (bindable != null && bindable is BasePage basePage)
49 | basePage.SetPageMode((PageMode)newValue);
50 | }
51 |
52 | private static void OnPageActionPropertyChanged(BindableObject bindable, object oldValue, object newValue)
53 | {
54 | if (bindable != null && bindable is BasePage basePage)
55 | basePage.SetPageAction((PageAction)newValue);
56 | }
57 | #endregion
58 |
59 | public BasePage()
60 | {
61 | InitializeComponent();
62 |
63 | //Hide the Xamarin Forms build in navigation header
64 | NavigationPage.SetHasNavigationBar(this, false);
65 |
66 | //Initialize the page mode
67 | SetPageMode(PageMode.None);
68 |
69 | //Initialize the page action
70 | SetPageAction(PageAction.None);
71 |
72 | //Fix top page marging requirement depending on the current device running the app
73 | StatusRowDefinition.Height = DependencyService.Get().StatusbarHeight;
74 | }
75 |
76 | private void SetPageMode(PageMode pageMode)
77 | {
78 | //((ViewModelBase)BindingContext).PageMode = pageMode;
79 |
80 | switch (pageMode)
81 | {
82 | case PageMode.Menu:
83 | //HamburgerButton.IsVisible = true;
84 | NavigateBackButton.IsVisible = false;
85 | //CloseButton.IsVisible = false;
86 | break;
87 | case PageMode.Navigate:
88 | //HamburgerButton.IsVisible = false;
89 | NavigateBackButton.IsVisible = true;
90 | //CloseButton.IsVisible = false;
91 | break;
92 | case PageMode.Modal:
93 | //HamburgerButton.IsVisible = false;
94 | NavigateBackButton.IsVisible = false;
95 | //CloseButton.IsVisible = true;
96 | break;
97 | default:
98 | //HamburgerButton.IsVisible = false;
99 | NavigateBackButton.IsVisible = false;
100 | break;
101 | }
102 |
103 | //HandleHamburgerMenuGesture(PageMode == PageMode.Menu);
104 | }
105 |
106 | private void SetPageAction(PageAction pageAction)
107 | {
108 | switch(pageAction)
109 | {
110 | case PageAction.Settings:
111 | SettingsButton.IsVisible = true;
112 | break;
113 | default:
114 | SettingsButton.IsVisible = false;
115 | break;
116 | }
117 | }
118 | }
119 | }
--------------------------------------------------------------------------------
/frontend/BirdAtlas/Views/SettingsPage.xaml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/frontend/BirdAtlas/Views/SettingsPage.xaml.cs:
--------------------------------------------------------------------------------
1 | namespace BirdAtlas.Views
2 | {
3 | public partial class SettingsPage : BasePage
4 | {
5 | public SettingsPage()
6 | {
7 | InitializeComponent();
8 | }
9 | }
10 | }
--------------------------------------------------------------------------------
/frontend/BirdAtlas/Views/StartPage.xaml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
20 |
21 |
22 |
23 |
24 |
25 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/frontend/BirdAtlas/Views/StartPage.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using Sharpnado.Tabs;
4 | using Xamarin.Forms;
5 |
6 | namespace BirdAtlas.Views
7 | {
8 | public partial class StartPage : BasePage
9 | {
10 | public StartPage()
11 | {
12 | InitializeComponent();
13 | }
14 |
15 | private void OnTabHostSelectedTabIndexChanged(Object sender, SelectedPositionChangedEventArgs e)
16 | {
17 | BasePageTitle = ((BottomTabItem)TabHost.Tabs[TabHost.SelectedIndex]).Label;
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/frontend/BirdAtlas/Views/StoryDetailPage.xaml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
12 |
14 |
16 |
17 |
18 |
19 |
20 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/frontend/BirdAtlas/Views/StoryDetailPage.xaml.cs:
--------------------------------------------------------------------------------
1 | namespace BirdAtlas.Views
2 | {
3 | public partial class StoryDetailPage : BasePage
4 | {
5 | public StoryDetailPage()
6 | {
7 | InitializeComponent();
8 | }
9 | }
10 | }
--------------------------------------------------------------------------------
/frontend/BirdAtlas/Views/StoryOverviewPage.xaml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
12 |
15 |
16 |
20 |
21 |
24 |
25 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/frontend/BirdAtlas/Views/StoryOverviewPage.xaml.cs:
--------------------------------------------------------------------------------
1 | namespace BirdAtlas.Views
2 | {
3 | public partial class StoryOverviewPage : BasePage
4 | {
5 | public StoryOverviewPage()
6 | {
7 | InitializeComponent();
8 | }
9 | }
10 | }
--------------------------------------------------------------------------------
/frontend/BirdAtlas/Views/TabViews/BookmarkTabView.xaml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/frontend/BirdAtlas/Views/TabViews/BookmarkTabView.xaml.cs:
--------------------------------------------------------------------------------
1 | using Xamarin.Forms;
2 |
3 | namespace BirdAtlas.Views.TabViews
4 | {
5 | public partial class BookmarkTabView : ContentView
6 | {
7 | public BookmarkTabView()
8 | {
9 | InitializeComponent();
10 | }
11 | }
12 | }
--------------------------------------------------------------------------------
/frontend/BirdAtlas/Views/TabViews/DiscoverTabView.xaml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
13 |
15 |
16 |
17 |
18 |
19 |
20 |
24 |
25 |
33 |
34 |
35 |
41 |
42 |
44 |
45 |
46 |
47 |
48 |
49 |
53 |
54 |
58 |
59 |
60 |
65 |
66 |
68 |
69 |
70 |
71 |
72 |
73 |
77 |
78 |
82 |
83 |
84 |
97 |
98 |
107 |
108 |
109 |
110 |
111 |
--------------------------------------------------------------------------------
/frontend/BirdAtlas/Views/TabViews/DiscoverTabView.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using Xamarin.Forms;
4 |
5 | namespace BirdAtlas.Views.TabViews
6 | {
7 | public partial class DiscoverTabView : ContentView
8 | {
9 | public DiscoverTabView()
10 | {
11 | InitializeComponent();
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/frontend/BirdAtlas/Views/TabViews/SearchTabView.xaml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/frontend/BirdAtlas/Views/TabViews/SearchTabView.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using Xamarin.Forms;
4 |
5 | namespace BirdAtlas.Views.TabViews
6 | {
7 | public partial class SearchTabView : ContentView
8 | {
9 | public SearchTabView()
10 | {
11 | InitializeComponent();
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/frontend/BirdAtlas/XamlResources/DataTemplates.xaml.cs:
--------------------------------------------------------------------------------
1 | using Xamarin.Forms;
2 |
3 | namespace BirdAtlas.XamlResources
4 | {
5 | public partial class DataTemplates : ResourceDictionary
6 | {
7 | public DataTemplates()
8 | {
9 | InitializeComponent();
10 | }
11 | }
12 | }
--------------------------------------------------------------------------------
/frontend/BirdAtlas/XamlResources/Styles.xaml.cs:
--------------------------------------------------------------------------------
1 | using Xamarin.Forms;
2 |
3 | namespace BirdAtlas.XamlResources
4 | {
5 | public partial class Styles : ResourceDictionary
6 | {
7 | public Styles()
8 | {
9 | InitializeComponent();
10 | }
11 | }
12 | }
--------------------------------------------------------------------------------
/frontend_flutter/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .buildlog/
9 | .history
10 | .svn/
11 |
12 | # IntelliJ related
13 | *.iml
14 | *.ipr
15 | *.iws
16 | .idea/
17 |
18 | # The .vscode folder contains launch configuration and tasks you configure in
19 | # VS Code which you may wish to be included in version control, so this line
20 | # is commented out by default.
21 | #.vscode/
22 |
23 | # Flutter/Dart/Pub related
24 | **/doc/api/
25 | **/ios/Flutter/.last_build_id
26 | .dart_tool/
27 | .flutter-plugins
28 | .flutter-plugins-dependencies
29 | .packages
30 | .pub-cache/
31 | .pub/
32 | /build/
33 |
34 | # Web related
35 | lib/generated_plugin_registrant.dart
36 |
37 | # Symbolication related
38 | app.*.symbols
39 |
40 | # Obfuscation related
41 | app.*.map.json
42 |
--------------------------------------------------------------------------------
/frontend_flutter/.metadata:
--------------------------------------------------------------------------------
1 | # This file tracks properties of this Flutter project.
2 | # Used by Flutter tool to assess capabilities and perform upgrades etc.
3 | #
4 | # This file should be version controlled.
5 |
6 | version:
7 | revision: 90c64ed42ba53a52d18f0cb3b17666c8662ed2a0
8 | channel: stable
9 |
10 | project_type: app
11 |
12 | # Tracks metadata for the flutter migrate command
13 | migration:
14 | platforms:
15 | - platform: root
16 | create_revision: 90c64ed42ba53a52d18f0cb3b17666c8662ed2a0
17 | base_revision: 90c64ed42ba53a52d18f0cb3b17666c8662ed2a0
18 | - platform: android
19 | create_revision: 90c64ed42ba53a52d18f0cb3b17666c8662ed2a0
20 | base_revision: 90c64ed42ba53a52d18f0cb3b17666c8662ed2a0
21 | - platform: ios
22 | create_revision: 90c64ed42ba53a52d18f0cb3b17666c8662ed2a0
23 | base_revision: 90c64ed42ba53a52d18f0cb3b17666c8662ed2a0
24 | - platform: linux
25 | create_revision: 90c64ed42ba53a52d18f0cb3b17666c8662ed2a0
26 | base_revision: 90c64ed42ba53a52d18f0cb3b17666c8662ed2a0
27 | - platform: macos
28 | create_revision: 90c64ed42ba53a52d18f0cb3b17666c8662ed2a0
29 | base_revision: 90c64ed42ba53a52d18f0cb3b17666c8662ed2a0
30 | - platform: web
31 | create_revision: 90c64ed42ba53a52d18f0cb3b17666c8662ed2a0
32 | base_revision: 90c64ed42ba53a52d18f0cb3b17666c8662ed2a0
33 | - platform: windows
34 | create_revision: 90c64ed42ba53a52d18f0cb3b17666c8662ed2a0
35 | base_revision: 90c64ed42ba53a52d18f0cb3b17666c8662ed2a0
36 |
37 | # User provided section
38 |
39 | # List of Local paths (relative to this file) that should be
40 | # ignored by the migrate tool.
41 | #
42 | # Files that are not part of the templates will be ignored by default.
43 | unmanaged_files:
44 | - 'lib/main.dart'
45 | - 'ios/Runner.xcodeproj/project.pbxproj'
46 |
--------------------------------------------------------------------------------
/frontend_flutter/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | // Use IntelliSense to learn about possible attributes.
3 | // Hover to view descriptions of existing attributes.
4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5 | "version": "0.2.0",
6 | "configurations": [
7 | {
8 | "name": "frontend_flutter",
9 | "request": "launch",
10 | "type": "dart"
11 | }
12 | ]
13 | }
--------------------------------------------------------------------------------
/frontend_flutter/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "cmake.configureOnOpen": false
3 | }
--------------------------------------------------------------------------------
/frontend_flutter/README.md:
--------------------------------------------------------------------------------
1 | # flutter_birdatlas
2 |
3 | A new Flutter project.
4 |
5 | ## Getting Started
6 |
7 | This project is a starting point for a Flutter application.
8 |
9 | A few resources to get you started if this is your first Flutter project:
10 |
11 | - [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab)
12 | - [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook)
13 |
14 | For help getting started with Flutter, view our
15 | [online documentation](https://flutter.dev/docs), which offers tutorials,
16 | samples, guidance on mobile development, and a full API reference.
17 |
--------------------------------------------------------------------------------
/frontend_flutter/analysis_options.yaml:
--------------------------------------------------------------------------------
1 | # This file configures the analyzer, which statically analyzes Dart code to
2 | # check for errors, warnings, and lints.
3 | #
4 | # The issues identified by the analyzer are surfaced in the UI of Dart-enabled
5 | # IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
6 | # invoked from the command line by running `flutter analyze`.
7 |
8 | # The following line activates a set of recommended lints for Flutter apps,
9 | # packages, and plugins designed to encourage good coding practices.
10 | include: package:flutter_lints/flutter.yaml
11 |
12 | linter:
13 | # The lint rules applied to this project can be customized in the
14 | # section below to disable rules from the `package:flutter_lints/flutter.yaml`
15 | # included above or to enable additional rules. A list of all available lints
16 | # and their documentation is published at
17 | # https://dart-lang.github.io/linter/lints/index.html.
18 | #
19 | # Instead of disabling a lint rule for the entire project in the
20 | # section below, it can also be suppressed for a single line of code
21 | # or a specific dart file by using the `// ignore: name_of_lint` and
22 | # `// ignore_for_file: name_of_lint` syntax on the line or in the file
23 | # producing the lint.
24 | rules:
25 | # avoid_print: false # Uncomment to disable the `avoid_print` rule
26 | # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
27 |
28 | # Additional information about this file can be found at
29 | # https://dart.dev/guides/language/analysis-options
30 |
--------------------------------------------------------------------------------
/frontend_flutter/android/.gitignore:
--------------------------------------------------------------------------------
1 | gradle-wrapper.jar
2 | /.gradle
3 | /captures/
4 | /gradlew
5 | /gradlew.bat
6 | /local.properties
7 | GeneratedPluginRegistrant.java
8 |
9 | # Remember to never publicly share your keystore.
10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
11 | key.properties
12 | **/*.keystore
13 | **/*.jks
14 |
--------------------------------------------------------------------------------
/frontend_flutter/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 flutter.compileSdkVersion
30 | ndkVersion flutter.ndkVersion
31 |
32 | compileOptions {
33 | sourceCompatibility JavaVersion.VERSION_1_8
34 | targetCompatibility JavaVersion.VERSION_1_8
35 | }
36 |
37 | kotlinOptions {
38 | jvmTarget = '1.8'
39 | }
40 |
41 | sourceSets {
42 | main.java.srcDirs += 'src/main/kotlin'
43 | }
44 |
45 | defaultConfig {
46 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
47 | applicationId "com.example.frontend_flutter"
48 | // You can update the following values to match your application needs.
49 | // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
50 | minSdkVersion flutter.minSdkVersion
51 | targetSdkVersion flutter.targetSdkVersion
52 | versionCode flutterVersionCode.toInteger()
53 | versionName flutterVersionName
54 | }
55 |
56 | buildTypes {
57 | release {
58 | // TODO: Add your own signing config for the release build.
59 | // Signing with the debug keys for now, so `flutter run --release` works.
60 | signingConfig signingConfigs.debug
61 | }
62 | }
63 | }
64 |
65 | flutter {
66 | source '../..'
67 | }
68 |
69 | dependencies {
70 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
71 | }
72 |
--------------------------------------------------------------------------------
/frontend_flutter/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
7 |
15 |
19 |
23 |
24 |
25 |
26 |
27 |
28 |
30 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/frontend_flutter/android/app/src/main/kotlin/com/example/frontend_flutter/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.example.frontend_flutter
2 |
3 | import io.flutter.embedding.android.FlutterActivity
4 |
5 | class MainActivity: FlutterActivity() {
6 | }
7 |
--------------------------------------------------------------------------------
/frontend_flutter/android/app/src/main/res/drawable-v21/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/frontend_flutter/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/frontend_flutter/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend_flutter/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/frontend_flutter/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend_flutter/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/frontend_flutter/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend_flutter/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/frontend_flutter/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend_flutter/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/frontend_flutter/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend_flutter/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/frontend_flutter/android/app/src/main/res/values-night/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/frontend_flutter/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/frontend_flutter/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/frontend_flutter/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | ext.kotlin_version = '1.7.10'
3 | repositories {
4 | google()
5 | mavenCentral()
6 | }
7 |
8 | dependencies {
9 | classpath 'com.android.tools.build:gradle:7.2.0'
10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
11 | }
12 | }
13 |
14 | allprojects {
15 | repositories {
16 | google()
17 | mavenCentral()
18 | }
19 | }
20 |
21 | rootProject.buildDir = '../build'
22 | subprojects {
23 | project.buildDir = "${rootProject.buildDir}/${project.name}"
24 | }
25 | subprojects {
26 | project.evaluationDependsOn(':app')
27 | }
28 |
29 | task clean(type: Delete) {
30 | delete rootProject.buildDir
31 | }
32 |
--------------------------------------------------------------------------------
/frontend_flutter/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1536M
2 | android.useAndroidX=true
3 | android.enableJetifier=true
4 |
--------------------------------------------------------------------------------
/frontend_flutter/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | zipStoreBase=GRADLE_USER_HOME
4 | zipStorePath=wrapper/dists
5 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip
6 |
--------------------------------------------------------------------------------
/frontend_flutter/android/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
3 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
4 | def properties = new Properties()
5 |
6 | assert localPropertiesFile.exists()
7 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
8 |
9 | def flutterSdkPath = properties.getProperty("flutter.sdk")
10 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
11 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
12 |
--------------------------------------------------------------------------------
/frontend_flutter/fonts/Montserrat-Light.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend_flutter/fonts/Montserrat-Light.ttf
--------------------------------------------------------------------------------
/frontend_flutter/fonts/Montserrat-Medium.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend_flutter/fonts/Montserrat-Medium.ttf
--------------------------------------------------------------------------------
/frontend_flutter/fonts/Montserrat-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend_flutter/fonts/Montserrat-Regular.ttf
--------------------------------------------------------------------------------
/frontend_flutter/fonts/Montserrat-SemiBold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend_flutter/fonts/Montserrat-SemiBold.ttf
--------------------------------------------------------------------------------
/frontend_flutter/ios/.gitignore:
--------------------------------------------------------------------------------
1 | **/dgph
2 | *.mode1v3
3 | *.mode2v3
4 | *.moved-aside
5 | *.pbxuser
6 | *.perspectivev3
7 | **/*sync/
8 | .sconsign.dblite
9 | .tags*
10 | **/.vagrant/
11 | **/DerivedData/
12 | Icon?
13 | **/Pods/
14 | **/.symlinks/
15 | profile
16 | xcuserdata
17 | **/.generated/
18 | Flutter/App.framework
19 | Flutter/Flutter.framework
20 | Flutter/Flutter.podspec
21 | Flutter/Generated.xcconfig
22 | Flutter/ephemeral/
23 | Flutter/app.flx
24 | Flutter/app.zip
25 | Flutter/flutter_assets/
26 | Flutter/flutter_export_environment.sh
27 | ServiceDefinitions.json
28 | Runner/GeneratedPluginRegistrant.*
29 |
30 | # Exceptions to above rules.
31 | !default.mode1v3
32 | !default.mode2v3
33 | !default.pbxuser
34 | !default.perspectivev3
35 |
--------------------------------------------------------------------------------
/frontend_flutter/ios/Flutter/AppFrameworkInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | App
9 | CFBundleIdentifier
10 | io.flutter.flutter.app
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | App
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1.0
23 | MinimumOSVersion
24 | 11.0
25 |
26 |
27 |
--------------------------------------------------------------------------------
/frontend_flutter/ios/Flutter/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/frontend_flutter/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/frontend_flutter/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/frontend_flutter/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/frontend_flutter/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/frontend_flutter/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
37 |
38 |
39 |
40 |
41 |
42 |
52 |
54 |
60 |
61 |
62 |
63 |
69 |
71 |
77 |
78 |
79 |
80 |
82 |
83 |
86 |
87 |
88 |
--------------------------------------------------------------------------------
/frontend_flutter/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/frontend_flutter/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/frontend_flutter/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/frontend_flutter/ios/Runner/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import Flutter
3 |
4 | @UIApplicationMain
5 | @objc class AppDelegate: FlutterAppDelegate {
6 | override func application(
7 | _ application: UIApplication,
8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
9 | ) -> Bool {
10 | GeneratedPluginRegistrant.register(with: self)
11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/frontend_flutter/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 |
--------------------------------------------------------------------------------
/frontend_flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend_flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
--------------------------------------------------------------------------------
/frontend_flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend_flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
--------------------------------------------------------------------------------
/frontend_flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend_flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
--------------------------------------------------------------------------------
/frontend_flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend_flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
--------------------------------------------------------------------------------
/frontend_flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend_flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
--------------------------------------------------------------------------------
/frontend_flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend_flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
--------------------------------------------------------------------------------
/frontend_flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend_flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
--------------------------------------------------------------------------------
/frontend_flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend_flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
--------------------------------------------------------------------------------
/frontend_flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend_flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
--------------------------------------------------------------------------------
/frontend_flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend_flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
--------------------------------------------------------------------------------
/frontend_flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend_flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
--------------------------------------------------------------------------------
/frontend_flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend_flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
--------------------------------------------------------------------------------
/frontend_flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend_flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
--------------------------------------------------------------------------------
/frontend_flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend_flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
--------------------------------------------------------------------------------
/frontend_flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend_flutter/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/frontend_flutter/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 |
--------------------------------------------------------------------------------
/frontend_flutter/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend_flutter/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/frontend_flutter/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend_flutter/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/frontend_flutter/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend_flutter/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
--------------------------------------------------------------------------------
/frontend_flutter/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.
--------------------------------------------------------------------------------
/frontend_flutter/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 |
--------------------------------------------------------------------------------
/frontend_flutter/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 |
--------------------------------------------------------------------------------
/frontend_flutter/ios/Runner/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleDisplayName
8 | Frontend Flutter
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | frontend_flutter
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | $(FLUTTER_BUILD_NAME)
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | $(FLUTTER_BUILD_NUMBER)
25 | LSRequiresIPhoneOS
26 |
27 | UILaunchStoryboardName
28 | LaunchScreen
29 | UIMainStoryboardFile
30 | Main
31 | UISupportedInterfaceOrientations
32 |
33 | UIInterfaceOrientationPortrait
34 | UIInterfaceOrientationLandscapeLeft
35 | UIInterfaceOrientationLandscapeRight
36 |
37 | UISupportedInterfaceOrientations~ipad
38 |
39 | UIInterfaceOrientationPortrait
40 | UIInterfaceOrientationPortraitUpsideDown
41 | UIInterfaceOrientationLandscapeLeft
42 | UIInterfaceOrientationLandscapeRight
43 |
44 | UIViewControllerBasedStatusBarAppearance
45 |
46 | CADisableMinimumFrameDurationOnPhone
47 |
48 | UIApplicationSupportsIndirectInputEvents
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/frontend_flutter/ios/Runner/Runner-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import "GeneratedPluginRegistrant.h"
2 |
--------------------------------------------------------------------------------
/frontend_flutter/lib/main.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter/services.dart';
3 | import 'package:flutter_birdatlas/services/birdatlasAPIInterface.dart';
4 | import 'package:flutter_birdatlas/services/birdatlasAPIMocked.dart';
5 | import 'package:flutter_birdatlas/main/mainPage.dart';
6 | import 'package:get_it/get_it.dart';
7 |
8 | GetIt getIt = GetIt.instance;
9 |
10 | void main() {
11 | // SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
12 | // systemNavigationBarColor: Colors.white, // navigation bar color
13 | // statusBarColor: Colors.white, // status bar color
14 | // statusBarBrightness: Brightness.light, //status bar brigtness
15 | // statusBarIconBrightness: Brightness.light, //status barIcon Brightness
16 | // systemNavigationBarDividerColor:
17 | // Colors.greenAccent, //Navigation bar divider color
18 | // systemNavigationBarIconBrightness: Brightness.light,
19 | // )); //navigation bar icon
20 |
21 | getIt
22 | .registerLazySingleton(() => BirdAtlasAPIMocked());
23 |
24 | runApp(BirdAtlasApp());
25 | }
26 |
27 | class BirdAtlasApp extends StatelessWidget {
28 | @override
29 | Widget build(BuildContext context) {
30 | return MaterialApp(
31 | title: 'Bird Atlas',
32 | theme: ThemeData(
33 | primarySwatch: Colors.blue,
34 | visualDensity: VisualDensity.adaptivePlatformDensity,
35 | appBarTheme: AppBarTheme(
36 | systemOverlayStyle: SystemUiOverlayStyle
37 | .dark), // https://sarunw.com/posts/how-to-change-status-bar-text-color-in-flutter/
38 | ),
39 | //home: SafeArea(child: MainPage()), //SafeArea not needed, the AppBar takes care of it
40 | home: MainPage(),
41 | debugShowCheckedModeBanner: false,
42 | );
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/frontend_flutter/lib/main/mainPage.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_birdatlas/main/tabs/bookmarkTab.dart';
3 | import 'package:flutter_birdatlas/main/tabs/discoverTab.dart';
4 | import 'package:flutter_birdatlas/main/tabs/searchTab.dart';
5 | import 'package:flutter_birdatlas/models.dart';
6 | import 'package:flutter_birdatlas/styles.dart';
7 |
8 | class MainPage extends StatefulWidget {
9 | const MainPage({Key? key}) : super(key: key);
10 |
11 | @override
12 | State createState() => _MainPageState();
13 | }
14 |
15 | class _MainPageState extends State {
16 | int _selectedTabIndex = 0;
17 |
18 | static List _tabs = [
19 | DiscoverTab(),
20 | SearchTab(),
21 | BookMarkTab(),
22 | ];
23 |
24 | void _onItemTapped(int index) {
25 | setState(() {
26 | _selectedTabIndex = index;
27 | });
28 | }
29 |
30 | @override
31 | Widget build(BuildContext context) {
32 | return Scaffold(
33 | body: Center(
34 | child: _tabs.elementAt(_selectedTabIndex),
35 | ),
36 | bottomNavigationBar: BottomNavigationBar(
37 | items: const [
38 | BottomNavigationBarItem(
39 | icon: Icon(Icons.home),
40 | label: '',
41 | ),
42 | BottomNavigationBarItem(
43 | icon: Icon(Icons.business),
44 | label: '',
45 | ),
46 | BottomNavigationBarItem(
47 | icon: Icon(Icons.school),
48 | label: '',
49 | ),
50 | ],
51 | currentIndex: _selectedTabIndex,
52 | selectedItemColor: AppColors[ColorValue.ligthBlue],
53 | showSelectedLabels: false,
54 | showUnselectedLabels: false,
55 | onTap: _onItemTapped,
56 | ),
57 | );
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/frontend_flutter/lib/main/tabs/bookmarkTab.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_birdatlas/main/tabs/tabAppBar.dart';
3 |
4 | class BookMarkTab extends StatelessWidget {
5 | @override
6 | Widget build(BuildContext context) {
7 | return Scaffold(
8 | appBar: TabAppBar('Bookmarked'),
9 | body: Text('Index 2: School'),
10 | );
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/frontend_flutter/lib/main/tabs/searchTab.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_birdatlas/main/tabs/tabAppBar.dart';
3 |
4 | class SearchTab extends StatelessWidget {
5 | @override
6 | Widget build(BuildContext context) {
7 | return Scaffold(
8 | appBar: TabAppBar('Search'),
9 | body: Text('Index 1: Business'),
10 | );
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/frontend_flutter/lib/main/tabs/tabAppBar.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_birdatlas/styles.dart';
3 |
4 | class TabAppBar extends StatefulWidget implements PreferredSizeWidget {
5 | final String title;
6 |
7 | TabAppBar(this.title, {Key? key})
8 | : preferredSize = Size.fromHeight(kToolbarHeight),
9 | super(key: key);
10 |
11 | @override
12 | final Size preferredSize; // default is 56.0
13 |
14 | @override
15 | _TabAppBarState createState() => _TabAppBarState(title);
16 | }
17 |
18 | class _TabAppBarState extends State {
19 | final String title;
20 |
21 | _TabAppBarState(this.title);
22 |
23 | @override
24 | Widget build(BuildContext context) {
25 | return AppBar(
26 | elevation: 0, //Remove the shadow line
27 | backgroundColor: Colors.transparent,
28 | actionsIconTheme: IconThemeData(size: 20.0, color: Colors.black),
29 | actions: [
30 | Padding(
31 | padding: EdgeInsets.only(right: 20.0),
32 | child: GestureDetector(
33 | onTap: () => print('Tap - setting'),
34 | child: Icon(
35 | Icons.tune,
36 | )))
37 | ],
38 | title: Text(title, style: pageTitleTextStyle),
39 | );
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/frontend_flutter/lib/models.dart:
--------------------------------------------------------------------------------
1 | import 'dart:ui';
2 |
3 | import 'package:flutter_birdatlas/styles.dart';
4 |
5 | enum ColorValue { dark, ligthBlue, warmBlue, darkBlue }
6 |
7 | enum HabitatType {
8 | Forest,
9 | Grassland,
10 | Tundra,
11 | Desert,
12 | Wetland,
13 | Ocean,
14 | UrbanSuburban
15 | }
16 |
17 | class Story {
18 | int? id;
19 | String? title;
20 | String? category;
21 | String? author;
22 | String? image;
23 | bool? isFeatured;
24 | }
25 |
26 | class Habitat {
27 | String? name;
28 | HabitatType? type;
29 | int? amount;
30 | Color? get color {
31 | switch (type) {
32 | case HabitatType.Grassland:
33 | case HabitatType.Tundra:
34 | return AppColors[ColorValue.warmBlue];
35 | case HabitatType.Forest:
36 | case HabitatType.Wetland:
37 | case HabitatType.UrbanSuburban:
38 | return AppColors[ColorValue.ligthBlue];
39 | case HabitatType.Desert:
40 | case HabitatType.Ocean:
41 | return AppColors[ColorValue.darkBlue];
42 | default:
43 | return AppColors[ColorValue.dark];
44 | }
45 | }
46 | }
47 |
48 | class Nearby {
49 | String? image;
50 | String? name;
51 | }
52 |
53 | /*
54 | // In Dart it is not needed to wrap fields into get/set if the getter and setters don't add value
55 | class ToDo {
56 | String _title;
57 | bool _done;
58 |
59 | String get title => _title;
60 | void set title(String newTitle) { _title = newTitle; }
61 |
62 | bool get _done => _done
63 | void set done(bool done) { _done = done; }
64 | }
65 | */
66 |
--------------------------------------------------------------------------------
/frontend_flutter/lib/services/birdatlasAPIInterface.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_birdatlas/models.dart';
3 |
4 | abstract class BirdAtlasAPIInterface extends ChangeNotifier {
5 | Future> getStories();
6 | Future getStory(int id);
7 | }
8 |
--------------------------------------------------------------------------------
/frontend_flutter/lib/services/birdatlasAPIMocked.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter_birdatlas/models.dart';
2 | import 'package:flutter_birdatlas/services/birdatlasAPIInterface.dart';
3 |
4 | class BirdAtlasAPIMocked extends BirdAtlasAPIInterface {
5 | late List _stories;
6 |
7 | BirdAtlasAPIMocked() {
8 | _initStories();
9 | }
10 |
11 | Future> getStories() async {
12 | //TODO: Glenn - dummy delay to test the async loading
13 | return Future.delayed(Duration(seconds: 5)).then((value) => _stories);
14 | }
15 |
16 | Future getStory(int id) async {
17 | throw UnimplementedError();
18 | }
19 |
20 | void _initStories() {
21 | _stories = {
22 | Story()
23 | ..id = 1
24 | ..title = 'Why we need to save the scavengers?'
25 | ..category = 'The Wilds'
26 | ..image = 'https://placekitten.com/800/600',
27 | Story()
28 | ..id = 2
29 | ..title = 'Drunk birds? What is happening...'
30 | ..category = 'Science'
31 | ..image = 'https://placekitten.com/800/600',
32 | Story()
33 | ..id = 3
34 | ..title = 'Follow the great winter migration.'
35 | ..category = 'Science'
36 | ..image = 'https://placekitten.com/800/600',
37 | Story()
38 | ..id = 4
39 | ..title = 'Follow the great winter migration.'
40 | ..category = 'Science'
41 | ..image = 'https://placekitten.com/800/600',
42 | Story()
43 | ..id = 5
44 | ..title = 'Follow the great winter migration.'
45 | ..category = 'Science'
46 | ..image = 'https://placekitten.com/800/600',
47 | Story()
48 | ..id = 6
49 | ..title = 'Follow the great winter migration.'
50 | ..category = 'Science'
51 | ..image = 'https://placekitten.com/800/600',
52 | }.toList();
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/frontend_flutter/lib/styles.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_birdatlas/models.dart';
3 |
4 | const AppColors = {
5 | ColorValue.dark: Color(0xFF262D3A),
6 | ColorValue.ligthBlue: Color(0xFF6688FF),
7 | ColorValue.warmBlue: Color(0xFF3D60DB),
8 | ColorValue.darkBlue: Color(0xFF1235B2)
9 | };
10 |
11 | TextStyle montserratMedium11 = TextStyle(
12 | fontFamily: 'Montserrat',
13 | fontWeight: FontWeight.w500,
14 | fontSize: 11,
15 | );
16 |
17 | TextStyle montserratMedium13 = TextStyle(
18 | fontFamily: 'Montserrat',
19 | fontWeight: FontWeight.w500,
20 | fontSize: 13,
21 | );
22 |
23 | TextStyle montserratSemiBold14 = TextStyle(
24 | fontFamily: 'Montserrat',
25 | fontWeight: FontWeight.w700,
26 | fontSize: 14,
27 | );
28 |
29 | TextStyle montserratSemiBold16 = TextStyle(
30 | fontFamily: 'Montserrat',
31 | fontWeight: FontWeight.w700,
32 | fontSize: 16,
33 | );
34 |
35 | //TODO: Glenn - read https://flutter.dev/docs/cookbook/design/themes
36 | TextStyle pageTitleTextStyle = TextStyle(
37 | color: Colors.black,
38 | fontFamily: 'Montserrat',
39 | fontWeight: FontWeight.w700,
40 | fontSize: 18);
41 |
42 | TextStyle categoryTextStyle = montserratSemiBold16;
43 |
44 | TextStyle categoryLinkTextStyle =
45 | montserratSemiBold14.copyWith(color: AppColors[ColorValue.warmBlue]);
46 |
47 | TextStyle storyTitleTextStyle =
48 | montserratMedium13.copyWith(color: Colors.black);
49 |
50 | TextStyle storyCategoryTextStyle =
51 | montserratMedium11.copyWith(color: Colors.black.withOpacity(0.5));
52 |
53 | TextStyle habitatTitleTextStyle =
54 | montserratSemiBold14.copyWith(color: Colors.white);
55 |
56 | TextStyle habitatDescriptionTextStyle =
57 | montserratSemiBold14.copyWith(color: Colors.white.withOpacity(0.6));
58 |
--------------------------------------------------------------------------------
/frontend_flutter/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: flutter_birdatlas
2 | description: A new Flutter project.
3 |
4 | # The following line prevents the package from being accidentally published to
5 | # pub.dev using `pub publish`. This is preferred for private packages.
6 | publish_to: 'none' # Remove this line if you wish to publish to pub.dev
7 |
8 | # The following defines the version and build number for your application.
9 | # A version number is three numbers separated by dots, like 1.2.43
10 | # followed by an optional build number separated by a +.
11 | # Both the version and the builder number may be overridden in flutter
12 | # build by specifying --build-name and --build-number, respectively.
13 | # In Android, build-name is used as versionName while build-number used as versionCode.
14 | # Read more about Android versioning at https://developer.android.com/studio/publish/versioning
15 | # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
16 | # Read more about iOS versioning at
17 | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
18 | version: 1.0.0+1
19 |
20 | environment:
21 | sdk: '>=3.2.3 <4.0.0'
22 |
23 | dependencies:
24 | flutter:
25 | sdk: flutter
26 |
27 | # The following adds the Cupertino Icons font to your application.
28 | # Use with the CupertinoIcons class for iOS style icons.
29 | cupertino_icons: ^1.0.0
30 | get_it: ^7.6.4
31 | flutter_staggered_animations: ^1.0.0
32 |
33 | dev_dependencies:
34 | flutter_test:
35 | sdk: flutter
36 |
37 | # For information on the generic Dart part of this file, see the
38 | # following page: https://dart.dev/tools/pub/pubspec
39 |
40 | # The following section is specific to Flutter.
41 | flutter:
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.dev/assets-and-images/#resolution-aware.
55 |
56 | # For details regarding adding assets from package dependencies, see
57 | # https://flutter.dev/assets-and-images/#from-packages
58 |
59 | fonts:
60 | - family: Montserrat
61 | fonts:
62 | - asset: fonts/Montserrat-Regular.ttf
63 | - asset: fonts/Montserrat-Light.ttf
64 | weight: 200
65 | - asset: fonts/Montserrat-Medium.ttf
66 | weight: 500
67 | - asset: fonts/Montserrat-SemiBold.ttf
68 | weight: 700
69 |
70 | # For details regarding fonts from package dependencies,
71 | # see https://flutter.dev/custom-fonts/#from-packages
72 |
--------------------------------------------------------------------------------
/frontend_maui/BirdAtlasMaui.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.31220.234
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BirdAtlasMaui", "BirdAtlasMaui\BirdAtlasMaui.csproj", "{CDE185B6-3C1F-429B-98A8-BCF3291F629A}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {CDE185B6-3C1F-429B-98A8-BCF3291F629A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {CDE185B6-3C1F-429B-98A8-BCF3291F629A}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {CDE185B6-3C1F-429B-98A8-BCF3291F629A}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
17 | {CDE185B6-3C1F-429B-98A8-BCF3291F629A}.Release|Any CPU.ActiveCfg = Release|Any CPU
18 | {CDE185B6-3C1F-429B-98A8-BCF3291F629A}.Release|Any CPU.Build.0 = Release|Any CPU
19 | {CDE185B6-3C1F-429B-98A8-BCF3291F629A}.Release|Any CPU.Deploy.0 = Release|Any CPU
20 | {20BED5F7-7645-4F4D-95D5-239404A8B07D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21 | {20BED5F7-7645-4F4D-95D5-239404A8B07D}.Debug|Any CPU.Build.0 = Debug|Any CPU
22 | {20BED5F7-7645-4F4D-95D5-239404A8B07D}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
23 | {20BED5F7-7645-4F4D-95D5-239404A8B07D}.Release|Any CPU.ActiveCfg = Release|Any CPU
24 | {20BED5F7-7645-4F4D-95D5-239404A8B07D}.Release|Any CPU.Build.0 = Release|Any CPU
25 | {20BED5F7-7645-4F4D-95D5-239404A8B07D}.Release|Any CPU.Deploy.0 = Release|Any CPU
26 | EndGlobalSection
27 | GlobalSection(SolutionProperties) = preSolution
28 | HideSolutionNode = FALSE
29 | EndGlobalSection
30 | GlobalSection(ExtensibilityGlobals) = postSolution
31 | SolutionGuid = {61F7FB11-1E47-470C-91E2-47F8143E1572}
32 | EndGlobalSection
33 | EndGlobal
34 |
--------------------------------------------------------------------------------
/frontend_maui/BirdAtlasMaui/App.xaml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 | #f9fade
10 | #262d3a
11 | #6688ff
12 | #3d60db
13 | #1235b2
14 |
15 |
19 |
20 |
24 |
25 |
29 |
30 |
34 |
35 |
39 |
40 |
44 |
45 |
49 |
50 |
54 |
55 |
57 |
58 |
61 |
62 |
66 |
67 |
70 |
71 |
73 |
74 |
77 |
78 |
80 |
81 |
85 |
86 |
88 |
89 |
92 |
93 |
96 |
97 |
99 |
100 |
101 |
102 |
103 |
104 |
--------------------------------------------------------------------------------
/frontend_maui/BirdAtlasMaui/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using BirdAtlasMaui.ViewModels;
3 | using BirdAtlasMaui.Views;
4 | using Microsoft.Extensions.DependencyInjection;
5 | using Microsoft.Maui;
6 | using Microsoft.Maui.Controls;
7 | using Microsoft.Maui.Controls.PlatformConfiguration.WindowsSpecific;
8 | using Application = Microsoft.Maui.Controls.Application;
9 |
10 | namespace BirdAtlasMaui
11 | {
12 | public partial class App : Application
13 | {
14 | public App(IServiceProvider serviceProvider)
15 | {
16 | InitializeComponent();
17 |
18 | MainPage = new NavigationPage(new MainPage(serviceProvider.GetRequiredService()));
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/frontend_maui/BirdAtlasMaui/BirdAtlasMaui.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | net6.0-ios;net6.0-android;net6.0-maccatalyst
6 | Exe
7 | true
8 | true
9 | BirdAtlasMaui
10 |
11 |
12 | BirdAtlasMaui
13 |
14 |
15 | com.companyname.BirdAtlasMaui
16 |
17 |
18 | 1.0
19 | 1
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 | true
45 | iossimulator-x64
46 | maccatalyst-x64
47 | False
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/frontend_maui/BirdAtlasMaui/Client/RestServiceFactory.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.Linq;
5 | using System.Net.Http;
6 | using System.Net.Http.Headers;
7 | using System.Threading;
8 | using System.Threading.Tasks;
9 | using Refit;
10 |
11 | namespace BirdAtlasMaui.API.Client
12 | {
13 | public class HttpLoggingHandler : DelegatingHandler
14 | {
15 | public HttpLoggingHandler(HttpMessageHandler innerHandler = null)
16 | : base(innerHandler ?? new HttpClientHandler())
17 | { }
18 | async protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
19 | {
20 | var req = request;
21 | var id = Guid.NewGuid().ToString();
22 | var msg = $"[{id} - Request]";
23 |
24 | Debug.WriteLine($"{msg}========Start==========");
25 | Debug.WriteLine($"{msg} {req.Method} {req.RequestUri.PathAndQuery} {req.RequestUri.Scheme}/{req.Version}");
26 | Debug.WriteLine($"{msg} Host: {req.RequestUri.Scheme}://{req.RequestUri.Host}");
27 |
28 | foreach (var header in req.Headers)
29 | Debug.WriteLine($"{msg} {header.Key}: {string.Join(", ", header.Value)}");
30 |
31 | if (req.Content != null)
32 | {
33 | foreach (var header in req.Content.Headers)
34 | Debug.WriteLine($"{msg} {header.Key}: {string.Join(", ", header.Value)}");
35 |
36 | if (req.Content is StringContent || this.IsTextBasedContentType(req.Headers) || this.IsTextBasedContentType(req.Content.Headers))
37 | {
38 | var result = await req.Content.ReadAsStringAsync();
39 |
40 | Debug.WriteLine($"{msg} Content:");
41 | Debug.WriteLine($"{msg} {string.Join("", result.Cast().Take(255))}...");
42 |
43 | }
44 | }
45 |
46 | var start = DateTime.Now;
47 |
48 | var response = await base.SendAsync(request, cancellationToken).ConfigureAwait(false);
49 |
50 | var end = DateTime.Now;
51 |
52 | Debug.WriteLine($"{msg} Duration: {end - start}");
53 | Debug.WriteLine($"{msg}==========End==========");
54 |
55 | msg = $"[{id} - Response]";
56 | Debug.WriteLine($"{msg}=========Start=========");
57 |
58 | var resp = response;
59 |
60 | Debug.WriteLine($"{msg} {req.RequestUri.Scheme.ToUpper()}/{resp.Version} {(int)resp.StatusCode} {resp.ReasonPhrase}");
61 |
62 | foreach (var header in resp.Headers)
63 | Debug.WriteLine($"{msg} {header.Key}: {string.Join(", ", header.Value)}");
64 |
65 | if (resp.Content != null)
66 | {
67 | foreach (var header in resp.Content.Headers)
68 | Debug.WriteLine($"{msg} {header.Key}: {string.Join(", ", header.Value)}");
69 |
70 | if (resp.Content is StringContent || this.IsTextBasedContentType(resp.Headers) || this.IsTextBasedContentType(resp.Content.Headers))
71 | {
72 | start = DateTime.Now;
73 | var result = await resp.Content.ReadAsStringAsync();
74 | end = DateTime.Now;
75 |
76 | Debug.WriteLine($"{msg} Content:");
77 | Debug.WriteLine($"{msg} {string.Join("", result.Cast().Take(255))}...");
78 | Debug.WriteLine($"{msg} Duration: {end - start}");
79 | }
80 | }
81 |
82 | Debug.WriteLine($"{msg}==========End==========");
83 | return response;
84 | }
85 |
86 | readonly string[] types = new[] { "html", "text", "xml", "json", "txt", "x-www-form-urlencoded" };
87 |
88 | bool IsTextBasedContentType(HttpHeaders headers)
89 | {
90 | IEnumerable values;
91 | if (!headers.TryGetValues("Content-Type", out values))
92 | return false;
93 | var header = string.Join(" ", values).ToLowerInvariant();
94 |
95 | return types.Any(t => header.Contains(t));
96 | }
97 | }
98 |
99 | ///
100 | /// Factory to create Refit REST services.
101 | ///
102 | public static class RestServiceFactory
103 | {
104 | ///
105 | /// Creates a new Refit RestService with the provided authentication.
106 | ///
107 | /// Interface type of service
108 | /// A Refit REST service instance for the requested API
109 | public static T CreateService()
110 | where T : class
111 | {
112 | var httpClient = new HttpClient(new HttpLoggingHandler()) { BaseAddress = new Uri(Constants.Constants.ApiHostUrl) };
113 | return RestService.For(httpClient);
114 | }
115 | }
116 | }
--------------------------------------------------------------------------------
/frontend_maui/BirdAtlasMaui/Constants/Constants.cs:
--------------------------------------------------------------------------------
1 | namespace BirdAtlasMaui.API.Constants
2 | {
3 | public static class Constants
4 | {
5 | public static string ApiHostUrl = "https://birdatlastemp.azurewebsites.net";
6 | }
7 | }
--------------------------------------------------------------------------------
/frontend_maui/BirdAtlasMaui/Models/Bird.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Text.Json.Serialization;
3 | using Refit;
4 |
5 | namespace BirdAtlasMaui.API.Models
6 | {
7 | public class Bird
8 | {
9 | [AliasAs("id")]
10 | public Guid Id { get; set; }
11 |
12 | [AliasAs("name")]
13 | public string Name { get; set; }
14 |
15 | [AliasAs("binomial")]
16 | public string Binomial { get; set; }
17 |
18 | [AliasAs("familyId")]
19 | public Guid FamilyId { get; set; }
20 |
21 | [AliasAs("family")]
22 | public string Family { get; set; }
23 |
24 | [AliasAs("description")]
25 | public string Description { get; set; }
26 |
27 | [AliasAs("imageUrl")]
28 | public string ImageUrl { get; set; }
29 |
30 | [AliasAs("habitat")]
31 | public string Habitat { get; set; }
32 |
33 | [AliasAs("diet")]
34 | public string Diet { get; set; }
35 |
36 | [AliasAs("nesting")]
37 | public string Nesting { get; set; }
38 |
39 | [AliasAs("population")]
40 | public string Population { get; set; }
41 |
42 | [AliasAs("location")]
43 | public string Location { get; set; }
44 |
45 | [AliasAs("recentSpottings")]
46 | public int RecentSpottings { get; set; }
47 |
48 | [AliasAs("favorited")]
49 | public bool Favorited { get; set; }
50 | }
51 | }
--------------------------------------------------------------------------------
/frontend_maui/BirdAtlasMaui/Models/Habitat.cs:
--------------------------------------------------------------------------------
1 | using Refit;
2 |
3 | namespace BirdAtlasMaui.API.Models
4 | {
5 | public class Habitat
6 | {
7 | [AliasAs("type")]
8 | public HabitatType HabitatType { get; set; }
9 |
10 | [AliasAs("name")]
11 | public string Name { get; set; }
12 |
13 | [AliasAs("birdCount")]
14 | public int BirdCount { get; set; }
15 |
16 | public string Amount => $"{BirdCount} birds";
17 | }
18 | }
--------------------------------------------------------------------------------
/frontend_maui/BirdAtlasMaui/Models/HabitatType.cs:
--------------------------------------------------------------------------------
1 | namespace BirdAtlasMaui.API.Models
2 | {
3 | public enum HabitatType
4 | {
5 | Forest,
6 | Grassland,
7 | Tundra,
8 | Desert,
9 | Wetland,
10 | Ocean,
11 | UrbanSuburban
12 | }
13 | }
--------------------------------------------------------------------------------
/frontend_maui/BirdAtlasMaui/Models/Story.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using BirdAtlasMaui.API.Models;
4 | using Refit;
5 |
6 | namespace BirdAtlasMaui.API.Models
7 | {
8 | public class Story
9 | {
10 | [AliasAs("id")]
11 | public Guid Id { get; set; }
12 |
13 | [AliasAs("imageUrl")]
14 | public string ImageUrl { get; set; }
15 |
16 | [AliasAs("category")]
17 | public string Category { get; set; }
18 |
19 | [AliasAs("title")]
20 | public string Title { get; set; }
21 |
22 | [AliasAs("isFeatured")]
23 | public bool IsFeatured { get; set; }
24 |
25 | [AliasAs("publishedOn")]
26 | public DateTime PublishedOn { get; set; }
27 |
28 | [AliasAs("author")]
29 | public string Author { get; set; }
30 |
31 | [AliasAs("content")]
32 | public string Content { get; set; }
33 |
34 | [AliasAs("relatedBirds")]
35 | public List RelatedBirds { get; set; }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/frontend_maui/BirdAtlasMaui/Platforms/Android/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/frontend_maui/BirdAtlasMaui/Platforms/Android/MainActivity.cs:
--------------------------------------------------------------------------------
1 | using Android.App;
2 | using Android.Content.PM;
3 | using Microsoft.Maui;
4 |
5 | namespace BirdAtlasMaui
6 | {
7 | [Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize)]
8 | public class MainActivity : MauiAppCompatActivity
9 | {
10 | }
11 | }
--------------------------------------------------------------------------------
/frontend_maui/BirdAtlasMaui/Platforms/Android/MainApplication.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Android.App;
3 | using Android.Runtime;
4 | using Microsoft.Maui;
5 |
6 | namespace BirdAtlasMaui
7 | {
8 | [Application]
9 | public class MainApplication : MauiApplication
10 | {
11 | public MainApplication(IntPtr handle, JniHandleOwnership ownership)
12 | : base(handle, ownership)
13 | {
14 | }
15 | }
16 | }
--------------------------------------------------------------------------------
/frontend_maui/BirdAtlasMaui/Platforms/Android/Resources/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #512BD4
4 | #2B0B98
5 | #2B0B98
6 |
--------------------------------------------------------------------------------
/frontend_maui/BirdAtlasMaui/Platforms/Android/Resources/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/frontend_maui/BirdAtlasMaui/Platforms/MacCatalyst/AppDelegate.cs:
--------------------------------------------------------------------------------
1 | using Foundation;
2 | using Microsoft.Maui;
3 |
4 | namespace BirdAtlasMaui
5 | {
6 | [Register("AppDelegate")]
7 | public class AppDelegate : MauiUIApplicationDelegate
8 | {
9 | }
10 | }
--------------------------------------------------------------------------------
/frontend_maui/BirdAtlasMaui/Platforms/MacCatalyst/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | LSMinimumSystemVersion
6 | 10.15
7 | UIDeviceFamily
8 |
9 | 1
10 | 2
11 |
12 | UIRequiredDeviceCapabilities
13 |
14 | arm64
15 |
16 | UISupportedInterfaceOrientations
17 |
18 | UIInterfaceOrientationPortrait
19 | UIInterfaceOrientationLandscapeLeft
20 | UIInterfaceOrientationLandscapeRight
21 |
22 | UISupportedInterfaceOrientations~ipad
23 |
24 | UIInterfaceOrientationPortrait
25 | UIInterfaceOrientationPortraitUpsideDown
26 | UIInterfaceOrientationLandscapeLeft
27 | UIInterfaceOrientationLandscapeRight
28 |
29 | XSAppIconAssets
30 | Assets.xcassets/appicon.appiconset
31 |
32 |
33 |
--------------------------------------------------------------------------------
/frontend_maui/BirdAtlasMaui/Platforms/MacCatalyst/Program.cs:
--------------------------------------------------------------------------------
1 | using UIKit;
2 |
3 | namespace BirdAtlasMaui
4 | {
5 | public class Program
6 | {
7 | // This is the main entry point of the application.
8 | static void Main(string[] args)
9 | {
10 | // if you want to use a different Application Delegate class from "AppDelegate"
11 | // you can specify it here.
12 | UIApplication.Main(args, null, typeof(AppDelegate));
13 | }
14 | }
15 | }
--------------------------------------------------------------------------------
/frontend_maui/BirdAtlasMaui/Platforms/iOS/AppDelegate.cs:
--------------------------------------------------------------------------------
1 | using Foundation;
2 | using Microsoft.Maui;
3 |
4 | namespace BirdAtlasMaui
5 | {
6 | [Register("AppDelegate")]
7 | public class AppDelegate : MauiUIApplicationDelegate
8 | {
9 | }
10 | }
--------------------------------------------------------------------------------
/frontend_maui/BirdAtlasMaui/Platforms/iOS/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | LSRequiresIPhoneOS
6 |
7 | MinimumOSVersion
8 | 10.3.4
9 | UIDeviceFamily
10 |
11 | 1
12 | 2
13 |
14 | UIRequiredDeviceCapabilities
15 |
16 | arm64
17 |
18 | UISupportedInterfaceOrientations
19 |
20 | UIInterfaceOrientationPortrait
21 | UIInterfaceOrientationLandscapeLeft
22 | UIInterfaceOrientationLandscapeRight
23 |
24 | UISupportedInterfaceOrientations~ipad
25 |
26 | UIInterfaceOrientationPortrait
27 | UIInterfaceOrientationPortraitUpsideDown
28 | UIInterfaceOrientationLandscapeLeft
29 | UIInterfaceOrientationLandscapeRight
30 |
31 | XSAppIconAssets
32 | Assets.xcassets/appicon.appiconset
33 |
34 |
35 |
--------------------------------------------------------------------------------
/frontend_maui/BirdAtlasMaui/Platforms/iOS/Program.cs:
--------------------------------------------------------------------------------
1 | using UIKit;
2 |
3 | namespace BirdAtlasMaui
4 | {
5 | public class Program
6 | {
7 | // This is the main entry point of the application.
8 | static void Main(string[] args)
9 | {
10 | // if you want to use a different Application Delegate class from "AppDelegate"
11 | // you can specify it here.
12 | UIApplication.Main(args, null, typeof(AppDelegate));
13 | }
14 | }
15 | }
--------------------------------------------------------------------------------
/frontend_maui/BirdAtlasMaui/Platforms/iOS/Resources/LaunchScreen.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
21 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/frontend_maui/BirdAtlasMaui/Resources/Fonts/OpenSans-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AppCreativity/BirdAtlas/7b4bb9ad6aecad58e660381a38adcd32af66d797/frontend_maui/BirdAtlasMaui/Resources/Fonts/OpenSans-Regular.ttf
--------------------------------------------------------------------------------
/frontend_maui/BirdAtlasMaui/Resources/appicon.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/frontend_maui/BirdAtlasMaui/Resources/appiconfg.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/frontend_maui/BirdAtlasMaui/Services/API/IBirdApi.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Threading.Tasks;
4 | using BirdAtlasMaui.API.Models;
5 | using Refit;
6 |
7 | namespace BirdAtlasMaui.API.Services
8 | {
9 | [Headers("Accept: application/json")]
10 | public interface IBirdApi
11 | {
12 | [Get("/birds?page={page}&amount={amount}")]
13 | Task> Birds(int page = 0, int amount = 10);
14 |
15 | [Get("/birds/{id}")]
16 | Task Bird(Guid id);
17 |
18 | [Put("/birds/{id}/favorite?favorite={favorite}")]
19 | Task Bird(Guid id, bool favorite);
20 | }
21 | }
--------------------------------------------------------------------------------
/frontend_maui/BirdAtlasMaui/Services/API/IHabitatApi.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Threading.Tasks;
4 | using BirdAtlasMaui.API.Models;
5 | using Refit;
6 |
7 | namespace BirdAtlasMaui.API.Services
8 | {
9 | [Headers("Accept: application/json")]
10 | public interface IHabitatApi
11 | {
12 | [Get("/habitats")]
13 | Task> Habitats();
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/frontend_maui/BirdAtlasMaui/Services/API/IStoryApi.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Threading.Tasks;
4 | using BirdAtlasMaui.API.Models;
5 | using Refit;
6 |
7 | namespace BirdAtlasMaui.API.Services
8 | {
9 | [Headers("Accept: application/json")]
10 | public interface IStoryApi
11 | {
12 | [Get("/stories?page={page}&amount={amount}")]
13 | Task> Stories(int page = 0, int amount = 10);
14 |
15 | [Get("/stories/featured?amount={amount}")]
16 | Task> FeaturedStories(int amount = 10);
17 | }
18 | }
--------------------------------------------------------------------------------
/frontend_maui/BirdAtlasMaui/Services/BirdService.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Threading.Tasks;
4 | using BirdAtlasMaui.API.Client;
5 | using BirdAtlasMaui.API.Models;
6 |
7 | namespace BirdAtlasMaui.API.Services
8 | {
9 | public class BirdService : IBirdApi
10 | {
11 | private readonly IBirdApi _birdApi;
12 |
13 | public BirdService()
14 | {
15 | _birdApi = RestServiceFactory.CreateService();
16 | }
17 |
18 | public Task> Birds(int page = 0, int amount = 10)
19 | {
20 | return _birdApi.Birds(page, amount);
21 | }
22 |
23 | public Task Bird(Guid id)
24 | {
25 | return _birdApi.Bird(id);
26 | }
27 |
28 | public Task Bird(Guid id, bool favorite)
29 | {
30 | return _birdApi.Bird(id, favorite);
31 | }
32 | }
33 | }
--------------------------------------------------------------------------------
/frontend_maui/BirdAtlasMaui/Services/HabitatService.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Threading.Tasks;
3 | using BirdAtlasMaui.API.Client;
4 | using BirdAtlasMaui.API.Models;
5 |
6 | namespace BirdAtlasMaui.API.Services
7 | {
8 | public class HabitatService : IHabitatApi
9 | {
10 | private readonly IHabitatApi _habitatApi;
11 |
12 | public HabitatService()
13 | {
14 | _habitatApi = RestServiceFactory.CreateService();
15 | }
16 |
17 | public Task> Habitats()
18 | {
19 | return _habitatApi.Habitats();
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/frontend_maui/BirdAtlasMaui/Services/StoryService.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Net;
3 | using System.Threading.Tasks;
4 | using BirdAtlasMaui.API.Client;
5 | using BirdAtlasMaui.API.Models;
6 |
7 | namespace BirdAtlasMaui.API.Services
8 | {
9 | public class StoryService : IStoryApi
10 | {
11 | private readonly IStoryApi _storyApi;
12 | private int _retry = 0;
13 |
14 | public StoryService()
15 | {
16 | _storyApi = RestServiceFactory.CreateService();
17 | }
18 |
19 | public Task> Stories(int page = 0, int amount = 10)
20 | {
21 | if (amount == 10)
22 | ++_retry;
23 |
24 | if (_retry < 3)
25 | return _storyApi.Stories(page, amount);
26 | else
27 | {
28 | _retry = 0;
29 | throw new WebException("Return dummy exception for debugging purpose");
30 | }
31 | }
32 |
33 | public async Task> FeaturedStories(int amount = 10)
34 | {
35 | var result = await _storyApi.FeaturedStories(amount);
36 | return result;
37 | }
38 | }
39 | }
--------------------------------------------------------------------------------
/frontend_maui/BirdAtlasMaui/Startup.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Maui;
2 | using Microsoft.Maui.Hosting;
3 | using Microsoft.Maui.Controls.Compatibility;
4 | using Microsoft.Maui.Controls.Hosting;
5 | using Microsoft.Maui.Controls.Xaml;
6 | using Microsoft.Extensions.DependencyInjection;
7 | using BirdAtlasMaui.API.Services;
8 | using BirdAtlasMaui.ViewModels;
9 |
10 | [assembly: XamlCompilationAttribute(XamlCompilationOptions.Compile)]
11 |
12 | namespace BirdAtlasMaui
13 | {
14 | public class Startup : IStartup
15 | {
16 | public void Configure(IAppHostBuilder appBuilder)
17 | {
18 | appBuilder
19 | .UseMauiApp()
20 | .UseMauiServiceProviderFactory(constructorInjection: true)
21 | .ConfigureServices(services =>
22 | {
23 | services.AddSingleton();
24 | services.AddSingleton();
25 | services.AddSingleton();
26 | services.AddTransient();
27 | services.AddTransient();
28 | services.AddTransient();
29 | })
30 | .ConfigureFonts(fonts =>
31 | {
32 | fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
33 | });
34 | }
35 | }
36 | }
--------------------------------------------------------------------------------
/frontend_maui/BirdAtlasMaui/ViewModels/BaseViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using System.Runtime.CompilerServices;
4 |
5 | namespace BirdAtlasMaui.ViewModels
6 | {
7 | public class BaseViewModel : INotifyPropertyChanged
8 | {
9 | public event PropertyChangedEventHandler PropertyChanged;
10 |
11 | protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) =>
12 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/frontend_maui/BirdAtlasMaui/ViewModels/BirdViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading.Tasks;
3 | using System.Windows.Input;
4 | using BirdAtlasMaui.API.Models;
5 | using BirdAtlasMaui.API.Services;
6 | using Microsoft.Maui.Controls;
7 |
8 | namespace BirdAtlasMaui.ViewModels
9 | {
10 | public class BirdViewModel : BaseViewModel
11 | {
12 | private IBirdApi _birdService;
13 |
14 | private Bird _bird;
15 | public Bird Bird
16 | {
17 | get => _bird;
18 | set
19 | {
20 | _bird = value;
21 | OnPropertyChanged();
22 | }
23 | }
24 |
25 | private ICommand _favoriteCommand;
26 | public ICommand FavoriteCommand => _favoriteCommand ?? (_favoriteCommand = new Command(async () => await Favorite()));
27 |
28 | public BirdViewModel(IBirdApi birdApi)
29 | {
30 | _birdService = birdApi;
31 | }
32 |
33 | public async Task Load()
34 | {
35 | var bird = await _birdService.Bird(Bird.Id);
36 | }
37 |
38 | public Task Favorite()
39 | {
40 | return _birdService.Bird(Bird.Id, true);
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/frontend_maui/BirdAtlasMaui/ViewModels/MainViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Collections.ObjectModel;
4 | using System.ComponentModel;
5 | using System.Runtime.CompilerServices;
6 | using System.Threading.Tasks;
7 | using System.Windows.Input;
8 | using BirdAtlasMaui.API.Models;
9 | using BirdAtlasMaui.API.Services;
10 | using BirdAtlasMaui.Views;
11 | using Microsoft.Extensions.DependencyInjection;
12 | using Microsoft.Maui.Controls;
13 |
14 | namespace BirdAtlasMaui.ViewModels
15 | {
16 | public class MainViewModel : BaseViewModel
17 | {
18 | private bool _loaded = false;
19 |
20 | private IServiceProvider _serviceProvider;
21 | private IStoryApi _storyService;
22 | private IHabitatApi _habitatService;
23 | private IBirdApi _birdService;
24 |
25 | private ObservableCollection _stories;
26 | public ObservableCollection Stories
27 | {
28 | get => _stories;
29 | set
30 | {
31 | if (value != null)
32 | {
33 | _stories = value;
34 | OnPropertyChanged();
35 | }
36 | }
37 | }
38 |
39 | private ObservableCollection _habitats;
40 | public ObservableCollection Habitats
41 | {
42 | get => _habitats;
43 | set
44 | {
45 | if (value != null)
46 | {
47 | _habitats = value;
48 | OnPropertyChanged();
49 | }
50 | }
51 | }
52 |
53 | private ObservableCollection _birds;
54 | public ObservableCollection Birds
55 | {
56 | get => _birds;
57 | set
58 | {
59 | if (value != null)
60 | {
61 | _birds = value;
62 | OnPropertyChanged();
63 | }
64 | }
65 | }
66 |
67 | private Bird _selectedBird;
68 | public Bird SelectedBird
69 | {
70 | get => _selectedBird;
71 | set
72 | {
73 | if (value != null)
74 | {
75 | _selectedBird = value;
76 | OnPropertyChanged();
77 |
78 | var birdPage = new BirdPage(_serviceProvider.GetRequiredService());
79 | ((BirdViewModel)birdPage.BindingContext).Bird = _selectedBird;
80 |
81 | (App.Current.MainPage as NavigationPage).PushAsync(birdPage);
82 | }
83 | }
84 | }
85 |
86 | private ICommand _showAllStoriesCommand;
87 | public ICommand ShowAllStoriesCommand => _showAllStoriesCommand ?? (_showAllStoriesCommand = new Command(() =>
88 | {
89 | var storiesPage = new StoriesPage(_serviceProvider.GetRequiredService());
90 | (App.Current.MainPage as NavigationPage).PushAsync(storiesPage);
91 | }));
92 |
93 | public MainViewModel(IServiceProvider serviceProvider, IStoryApi storyService, IHabitatApi habitatApi, IBirdApi birdApi)
94 | {
95 | _serviceProvider = serviceProvider;
96 | _storyService = storyService;
97 | _habitatService = habitatApi;
98 | _birdService = birdApi;
99 | }
100 |
101 | public async Task Load()
102 | {
103 | if (!_loaded)
104 | {
105 | await Task.WhenAll(new List()
106 | {
107 | { Task.Run(() => GetStoriesAsync()) },
108 | { Task.Run(() => GetHabitatsAsync()) },
109 | { Task.Run(() => GetBirdsAsync()) }
110 | });
111 | _loaded = true;
112 | }
113 | }
114 |
115 | private async Task GetStoriesAsync()
116 | {
117 | var stories = await _storyService.Stories(0, 4);
118 |
119 | App.Current.Dispatcher.BeginInvokeOnMainThread(() => Stories = new ObservableCollection(stories));
120 | }
121 |
122 | private async Task GetHabitatsAsync()
123 | {
124 | var habitats = await _habitatService.Habitats();
125 | habitats.Add(habitats[0]);
126 | habitats.Add(habitats[0]);
127 |
128 | App.Current.Dispatcher.BeginInvokeOnMainThread(() => Habitats = new ObservableCollection(habitats));
129 | }
130 |
131 | private async Task GetBirdsAsync()
132 | {
133 | var birds = await _birdService.Birds();
134 | App.Current.Dispatcher.BeginInvokeOnMainThread(() => Birds = new ObservableCollection(birds));
135 | }
136 | }
137 | }
--------------------------------------------------------------------------------
/frontend_maui/BirdAtlasMaui/ViewModels/StoriesViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Collections.ObjectModel;
4 | using System.Net;
5 | using System.Threading.Tasks;
6 | using BirdAtlasMaui.API.Models;
7 | using BirdAtlasMaui.API.Services;
8 | using Polly;
9 |
10 | namespace BirdAtlasMaui.ViewModels
11 | {
12 | public class StoriesViewModel : BaseViewModel
13 | {
14 | private IStoryApi _storyService;
15 |
16 | private ObservableCollection _stories;
17 | public ObservableCollection Stories
18 | {
19 | get => _stories;
20 | set
21 | {
22 | if (value != null)
23 | {
24 | _stories = value;
25 | OnPropertyChanged();
26 | }
27 | }
28 | }
29 |
30 | public StoriesViewModel(IStoryApi storyService)
31 | {
32 | _storyService = storyService;
33 | }
34 |
35 | public async Task Load()
36 | {
37 | //var stories = await _storyService.Stories();
38 | //var stories = await Policy.Handle().WaitAndRetryAsync(retryCount: 3, sleepDurationProvider: retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))).ExecuteAsync(async () => await _storyService.Stories());
39 |
40 | var stories = await Policy>
41 | .Handle()
42 | .FallbackAsync(async (System.Threading.CancellationToken arg) => await _storyService.FeaturedStories())
43 | .ExecuteAsync(async () => await _storyService.Stories());
44 |
45 | App.Current.Dispatcher.BeginInvokeOnMainThread(() => Stories = new ObservableCollection(stories));
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/frontend_maui/BirdAtlasMaui/Views/BirdPage.xaml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
9 |
12 |
13 |
14 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/frontend_maui/BirdAtlasMaui/Views/BirdPage.xaml.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Maui.Controls;
2 | using BirdAtlasMaui.ViewModels;
3 |
4 | namespace BirdAtlasMaui.Views
5 | {
6 | public partial class BirdPage : ContentPage
7 | {
8 | BirdViewModel _birdViewModel;
9 |
10 | public BirdPage(BirdViewModel viewModel)
11 | {
12 | InitializeComponent();
13 | BindingContext = _birdViewModel = viewModel;
14 | }
15 |
16 | protected override async void OnAppearing()
17 | {
18 | base.OnAppearing();
19 | await _birdViewModel.Load();
20 | }
21 | }
22 | }
--------------------------------------------------------------------------------
/frontend_maui/BirdAtlasMaui/Views/MainPage.xaml.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Maui.Controls;
2 | using BirdAtlasMaui.ViewModels;
3 |
4 | namespace BirdAtlasMaui.Views
5 | {
6 | public partial class MainPage : ContentPage
7 | {
8 | MainViewModel _mainViewModel;
9 |
10 | public MainPage(MainViewModel viewModel)
11 | {
12 | InitializeComponent();
13 | BindingContext = _mainViewModel = viewModel;
14 | }
15 |
16 | protected override async void OnAppearing()
17 | {
18 | base.OnAppearing();
19 |
20 | await _mainViewModel.Load();
21 | }
22 | }
23 | }
--------------------------------------------------------------------------------
/frontend_maui/BirdAtlasMaui/Views/StoriesPage.xaml:
--------------------------------------------------------------------------------
1 |
6 |
8 |
11 |
12 |
16 |
17 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
35 |
38 |
40 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/frontend_maui/BirdAtlasMaui/Views/StoriesPage.xaml.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Maui.Controls;
2 | using BirdAtlasMaui.ViewModels;
3 |
4 | namespace BirdAtlasMaui.Views
5 | {
6 | public partial class StoriesPage : ContentPage
7 | {
8 | StoriesViewModel _storiesViewModel;
9 |
10 | public StoriesPage(StoriesViewModel viewModel)
11 | {
12 | InitializeComponent();
13 | BindingContext = _storiesViewModel = viewModel;
14 | }
15 |
16 | protected override async void OnAppearing()
17 | {
18 | base.OnAppearing();
19 | await _storiesViewModel.Load();
20 | }
21 | }
22 | }
--------------------------------------------------------------------------------