├── iOS
├── Resources
│ ├── event.png
│ ├── event@2x.png
│ ├── event@3x.png
│ ├── Images.xcassets
│ │ └── AppIcons.appiconset
│ │ │ ├── Icon@2x.png
│ │ │ ├── Icon@3x.png
│ │ │ ├── Icon-Settings.png
│ │ │ ├── Icon-Small@2x.png
│ │ │ ├── Icon-Small@3x.png
│ │ │ ├── Icon-Settings@2x.png
│ │ │ ├── Icon-Settings@3x.png
│ │ │ └── Contents.json
│ └── LaunchScreen.storyboard
├── Entitlements.plist
├── Custom Controls
│ ├── NotifyButton.designer.cs
│ └── NotifyButton.cs
├── Main.cs
├── packages.config
├── Helpers
│ ├── Share.cs
│ ├── Utils.cs
│ ├── MessageDialog.cs
│ ├── ViewExtensions.cs
│ └── ReminderService.cs
├── Info.plist
├── PluginsHelp
│ └── SettingsReadme.txt
├── AppDelegate.cs
├── BaseViewController.cs
├── ViewController.designer.cs
├── ViewController.cs
├── SaveTheDate.iOS.csproj
└── Main.storyboard
├── Screenshots
└── SaveTheDate.png
├── Droid
├── Resources
│ ├── drawable-hdpi
│ │ ├── event.png
│ │ └── ic_launcher.png
│ ├── drawable-mdpi
│ │ ├── event.png
│ │ └── ic_launcher.png
│ ├── drawable-xhdpi
│ │ ├── event.png
│ │ └── ic_launcher.png
│ ├── drawable-xxhdpi
│ │ ├── event.png
│ │ └── ic_launcher.png
│ ├── drawable-xxxhdpi
│ │ └── ic_launcher.png
│ ├── values
│ │ ├── Strings.xml
│ │ ├── colors.xml
│ │ └── styles.xml
│ ├── values-v21
│ │ └── styles.xml
│ ├── AboutResources.txt
│ └── layout
│ │ └── Main.axml
├── DeviceInfoReadme.txt
├── Helpers
│ ├── AndroidUtils.cs
│ ├── Share.cs
│ ├── MessageDialog.cs
│ └── ReminderService.cs
├── Assets
│ └── AboutAssets.txt
├── Properties
│ ├── AndroidManifest.xml
│ └── AssemblyInfo.cs
├── packages.config
├── PluginsHelp
│ └── SettingsReadme.txt
├── MainActivity.cs
└── SaveTheDate.Droid.csproj
├── UITests
├── packages.config
├── AppInitializer.cs
├── UITests.csproj
└── Tests.cs
├── SaveTheDate
├── Interfaces
│ ├── IShare.cs
│ ├── IMessage.cs
│ └── IReminderService.cs
├── DeviceInfoReadme.txt
├── Helpers
│ ├── Strings.cs
│ ├── Utils.cs
│ └── Settings.cs
├── packages.config
├── Properties
│ └── AssemblyInfo.cs
├── RegexUtils.cs
├── SaveTheDateHelper.cs
└── SaveTheDate.csproj
├── README.md
├── SaveTheDate.userprefs
├── LICENSE
├── .gitignore
└── SaveTheDate.sln
/iOS/Resources/event.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xamarin/SaveTheDate/HEAD/iOS/Resources/event.png
--------------------------------------------------------------------------------
/iOS/Resources/event@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xamarin/SaveTheDate/HEAD/iOS/Resources/event@2x.png
--------------------------------------------------------------------------------
/iOS/Resources/event@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xamarin/SaveTheDate/HEAD/iOS/Resources/event@3x.png
--------------------------------------------------------------------------------
/Screenshots/SaveTheDate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xamarin/SaveTheDate/HEAD/Screenshots/SaveTheDate.png
--------------------------------------------------------------------------------
/Droid/Resources/drawable-hdpi/event.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xamarin/SaveTheDate/HEAD/Droid/Resources/drawable-hdpi/event.png
--------------------------------------------------------------------------------
/Droid/Resources/drawable-mdpi/event.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xamarin/SaveTheDate/HEAD/Droid/Resources/drawable-mdpi/event.png
--------------------------------------------------------------------------------
/Droid/Resources/drawable-xhdpi/event.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xamarin/SaveTheDate/HEAD/Droid/Resources/drawable-xhdpi/event.png
--------------------------------------------------------------------------------
/Droid/Resources/drawable-xxhdpi/event.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xamarin/SaveTheDate/HEAD/Droid/Resources/drawable-xxhdpi/event.png
--------------------------------------------------------------------------------
/Droid/Resources/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xamarin/SaveTheDate/HEAD/Droid/Resources/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Droid/Resources/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xamarin/SaveTheDate/HEAD/Droid/Resources/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Droid/Resources/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xamarin/SaveTheDate/HEAD/Droid/Resources/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Droid/Resources/drawable-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xamarin/SaveTheDate/HEAD/Droid/Resources/drawable-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Droid/Resources/drawable-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xamarin/SaveTheDate/HEAD/Droid/Resources/drawable-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/iOS/Resources/Images.xcassets/AppIcons.appiconset/Icon@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xamarin/SaveTheDate/HEAD/iOS/Resources/Images.xcassets/AppIcons.appiconset/Icon@2x.png
--------------------------------------------------------------------------------
/iOS/Resources/Images.xcassets/AppIcons.appiconset/Icon@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xamarin/SaveTheDate/HEAD/iOS/Resources/Images.xcassets/AppIcons.appiconset/Icon@3x.png
--------------------------------------------------------------------------------
/iOS/Resources/Images.xcassets/AppIcons.appiconset/Icon-Settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xamarin/SaveTheDate/HEAD/iOS/Resources/Images.xcassets/AppIcons.appiconset/Icon-Settings.png
--------------------------------------------------------------------------------
/iOS/Resources/Images.xcassets/AppIcons.appiconset/Icon-Small@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xamarin/SaveTheDate/HEAD/iOS/Resources/Images.xcassets/AppIcons.appiconset/Icon-Small@2x.png
--------------------------------------------------------------------------------
/iOS/Resources/Images.xcassets/AppIcons.appiconset/Icon-Small@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xamarin/SaveTheDate/HEAD/iOS/Resources/Images.xcassets/AppIcons.appiconset/Icon-Small@3x.png
--------------------------------------------------------------------------------
/iOS/Resources/Images.xcassets/AppIcons.appiconset/Icon-Settings@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xamarin/SaveTheDate/HEAD/iOS/Resources/Images.xcassets/AppIcons.appiconset/Icon-Settings@2x.png
--------------------------------------------------------------------------------
/iOS/Resources/Images.xcassets/AppIcons.appiconset/Icon-Settings@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xamarin/SaveTheDate/HEAD/iOS/Resources/Images.xcassets/AppIcons.appiconset/Icon-Settings@3x.png
--------------------------------------------------------------------------------
/Droid/Resources/values/Strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Hello World, Click Me!
4 | SaveTheDate.Droid
5 |
6 |
--------------------------------------------------------------------------------
/iOS/Entitlements.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/UITests/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/SaveTheDate/Interfaces/IShare.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace SaveTheDate.Interfaces
4 | {
5 | public interface IShare
6 | {
7 | void ShareText(string text);
8 | string GetEmail();
9 | }
10 | }
11 |
12 |
--------------------------------------------------------------------------------
/Droid/DeviceInfoReadme.txt:
--------------------------------------------------------------------------------
1 | Devic Info Readme
2 | Find the most up to date information at: https://github.com/jamesmontemagno/Xamarin.Plugins
3 |
4 | **IMPORTANT**
5 |
6 |
7 | Windows Phone:
8 | Permissions to add:
9 | ID_CAP_IDENTITY_DEVICE
--------------------------------------------------------------------------------
/SaveTheDate/DeviceInfoReadme.txt:
--------------------------------------------------------------------------------
1 | Devic Info Readme
2 | Find the most up to date information at: https://github.com/jamesmontemagno/Xamarin.Plugins
3 |
4 | **IMPORTANT**
5 |
6 |
7 | Windows Phone:
8 | Permissions to add:
9 | ID_CAP_IDENTITY_DEVICE
--------------------------------------------------------------------------------
/SaveTheDate/Helpers/Strings.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace SaveTheDate.Helpers
4 | {
5 | public static class Strings
6 | {
7 | public static readonly string ShareText = "I can't wait for EVENT in LOCATION on DATE: http://yoururl. Save the date now!";
8 | }
9 | }
10 |
11 |
--------------------------------------------------------------------------------
/Droid/Helpers/AndroidUtils.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Android.App;
3 | using Android.Views;
4 |
5 | namespace SaveTheDate.Droid.Helpers
6 | {
7 | public static partial class AndroidUtils
8 | {
9 | public static Activity Context { get; set; }
10 | public static View SnackbarView {get;set;}
11 | }
12 | }
13 |
14 |
--------------------------------------------------------------------------------
/SaveTheDate/Interfaces/IMessage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace SaveTheDate.Interfaces
4 | {
5 | public interface IMessage
6 | {
7 | void SendMessage(string message, string title = null);
8 | void SendToast(string message);
9 | void SendConfirmation(string message, string title, Action confirmationAction);
10 | }
11 | }
12 |
13 |
--------------------------------------------------------------------------------
/SaveTheDate/Helpers/Utils.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using SaveTheDate.Interfaces;
3 |
4 | namespace SaveTheDate.Helpers
5 | {
6 | public static partial class Utils
7 | {
8 | public static IShare Sharer { get; set; }
9 | public static IReminderService Reminder { get; set; }
10 | public static IMessage Message { get; set; }
11 | }
12 | }
13 |
14 |
--------------------------------------------------------------------------------
/SaveTheDate/Interfaces/IReminderService.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace SaveTheDate.Interfaces
4 | {
5 | public interface IReminderService
6 | {
7 | void AddEvent(DateTime startTime, DateTime endTime, string title, string location, string message, Actioncallback, string id);
8 | bool EventExists(DateTime startTime, string title, string id);
9 | void RemoveEvent(DateTime startDate, string title, string id);
10 | }
11 | }
12 |
13 |
--------------------------------------------------------------------------------
/iOS/Custom Controls/NotifyButton.designer.cs:
--------------------------------------------------------------------------------
1 | // WARNING
2 | //
3 | // This file has been generated automatically by Xamarin Studio from the outlets and
4 | // actions declared in your storyboard file.
5 | // Manual changes to this file will not be maintained.
6 | //
7 | using Foundation;
8 | using System;
9 | using System.CodeDom.Compiler;
10 | using UIKit;
11 |
12 | namespace SaveTheDate.iOS.CustomControls
13 | {
14 | [Register ("NotifyButton")]
15 | partial class NotifyButton
16 | {
17 | void ReleaseDesignerOutlets ()
18 | {
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/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 SaveTheDate.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 | }
21 |
--------------------------------------------------------------------------------
/Droid/Resources/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | #03A9F4
5 | #0D1A32
6 | #FFC107
7 | #B3E5FC
8 | #FFFFFF
9 | #212121
10 | #727272
11 | #B6B6B6
12 | #E8E8E8
13 |
--------------------------------------------------------------------------------
/Droid/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 your 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 |
--------------------------------------------------------------------------------
/iOS/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/Droid/Resources/values-v21/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
15 |
--------------------------------------------------------------------------------
/Droid/Properties/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Save The Date
2 | =============
3 |
4 | This pre-built template enables you to easily allow attendees of your conference to register for notifications of your upcoming event. They can easily add the event to their calendar and share it with their friends.
5 |
6 | 
7 |
8 | ## Customization
9 | Simply update the **RegisterForNotifications** method in SaveTheDateHelper.cs to register the user's email address in your backend system. Then just update your events name, logo, and date!
10 |
11 | This mobile app is brought to you by your friends at [Xamarin](http://www.xamarin.com/).
12 |
13 | ### Authors:
14 | - [James Montemagno](http://github.com/jamesmontemagno): [Twitter](http://twitter.com/jamesmontemagno) | [Blog](http://motzcod.es)
15 | - [Mike James](http://github.com/MikeCodesDotNet): [Twitter](http://twitter.com/mikecodesdotnet) | [Blog](http://mikecodes.net)
16 |
--------------------------------------------------------------------------------
/Droid/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/SaveTheDate.userprefs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/SaveTheDate/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/iOS/Helpers/Share.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using SaveTheDate.Interfaces;
3 | using Foundation;
4 | using UIKit;
5 |
6 | namespace SaveTheDate.iOS.Helpers
7 | {
8 | public class Share : IShare
9 | {
10 | public static UIViewController ViewController {get;set;}
11 | public async void ShareText (string text)
12 | {
13 | try
14 | {
15 | var items = new NSObject[] { new NSString (text) };
16 | var activityController = new UIActivityViewController (items, null);
17 | var vc = ViewController ?? UIApplication.SharedApplication.KeyWindow.RootViewController;
18 | await vc.PresentViewControllerAsync (activityController, true);
19 | }
20 | catch(Exception ex)
21 | {
22 | Xamarin.Insights.Report(ex);
23 | }
24 | }
25 |
26 |
27 | public string GetEmail ()
28 | {
29 | return string.Empty;
30 | }
31 | }
32 | }
33 |
34 |
--------------------------------------------------------------------------------
/iOS/Helpers/Utils.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Foundation;
3 |
4 | namespace SaveTheDate.iOS.Helpers
5 | {
6 | public static class Utils
7 | {
8 | public static NSObject Invoker;
9 | ///
10 | /// Ensures the invoked on main thread.
11 | ///
12 | /// Action to run on main thread.
13 | public static void EnsureInvokedOnMainThread (Action action)
14 | {
15 | if (NSThread.Current.IsMainThread) {
16 | action ();
17 | return;
18 | }
19 | if (Invoker == null)
20 | Invoker = new NSObject ();
21 |
22 | Invoker.BeginInvokeOnMainThread(action);
23 | }
24 |
25 | public static NSDate ToNSDate(this DateTime date)
26 | {
27 | if (date.Kind == DateTimeKind.Unspecified)
28 | date = DateTime.SpecifyKind(date, DateTimeKind.Utc);
29 |
30 | return (NSDate) date;
31 | }
32 |
33 | }
34 | }
35 |
36 |
--------------------------------------------------------------------------------
/SaveTheDate/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 |
4 | // Information about this assembly is defined by the following attributes.
5 | // Change them to the values specific to your project.
6 |
7 | [assembly: AssemblyTitle("SaveTheDate")]
8 | [assembly: AssemblyDescription("")]
9 | [assembly: AssemblyConfiguration("")]
10 | [assembly: AssemblyCompany("")]
11 | [assembly: AssemblyProduct("")]
12 | [assembly: AssemblyCopyright("jamesmontemagno")]
13 | [assembly: AssemblyTrademark("")]
14 | [assembly: AssemblyCulture("")]
15 |
16 | // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
17 | // The form "{Major}.{Minor}.*" will automatically update the build and revision,
18 | // and "{Major}.{Minor}.{Build}.*" will update just the revision.
19 |
20 | [assembly: AssemblyVersion("1.0.*")]
21 |
22 | // The following attributes are used to specify the signing key for the assembly,
23 | // if desired. See the Mono documentation for more information about signing.
24 |
25 | //[assembly: AssemblyDelaySign(false)]
26 | //[assembly: AssemblyKeyFile("")]
27 |
28 |
--------------------------------------------------------------------------------
/Droid/Helpers/Share.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Android.Accounts;
3 | using Android.Util;
4 | using Android.Content;
5 | using SaveTheDate.Interfaces;
6 | using SaveTheDate.Helpers;
7 |
8 | namespace SaveTheDate.Droid.Helpers
9 | {
10 | public class Share : IShare
11 | {
12 | public void ShareText (string text)
13 | {
14 | var intent = new Intent (Intent.ActionSend);
15 | intent.SetType ("text/plain");
16 | intent.PutExtra (Intent.ExtraText, text);
17 | AndroidUtils.Context.StartActivity (Intent.CreateChooser (intent, "Share Event"));
18 | }
19 |
20 |
21 |
22 | public string GetEmail ()
23 | {
24 | var emailPattern = Patterns.EmailAddress; // API level 8+
25 | var accounts = AccountManager.Get (AndroidUtils.Context).GetAccounts ();
26 | foreach (var account in accounts) {
27 | if (emailPattern.Matcher (account.Name).Matches ()) {
28 | return account.Name;
29 | }
30 | }
31 |
32 | return string.Empty;
33 | }
34 | }
35 | }
36 |
37 |
--------------------------------------------------------------------------------
/UITests/AppInitializer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Linq;
4 | using Xamarin.UITest;
5 | using Xamarin.UITest.Queries;
6 |
7 | namespace UITests
8 | {
9 | public class AppInitializer
10 | {
11 | public static IApp StartApp(Platform platform)
12 | {
13 | // TODO: If the iOS or Android app being tested is included in the solution
14 | // then open the Unit Tests window, right click Test Apps, select Add App Project
15 | // and select the app projects that should be tested.
16 | if (platform == Platform.Android)
17 | {
18 | return ConfigureApp
19 | .Android
20 | // TODO: Update this path to point to your Android app and uncomment the
21 | // code if the app is not included in the solution.
22 | .ApkFile ("../../../Droid/bin/Debug/com.company.SaveTheDate.apk")
23 | .StartApp();
24 | }
25 |
26 | return ConfigureApp.iOS.AppBundle("../../../iOS/bin/iPhoneSimulator/Debug/SaveTheDateiOS.app").StartApp();
27 | }
28 | }
29 | }
30 |
31 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Xamarin
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software is furnished to do so,
10 | 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, FITNESS
17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/Droid/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using Android.App;
4 |
5 | // Information about this assembly is defined by the following attributes.
6 | // Change them to the values specific to your project.
7 |
8 | [assembly: AssemblyTitle("SaveTheDate.Droid")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("")]
13 | [assembly: AssemblyCopyright("jamesmontemagno")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
18 | // The form "{Major}.{Minor}.*" will automatically update the build and revision,
19 | // and "{Major}.{Minor}.{Build}.*" will update just the revision.
20 |
21 | [assembly: AssemblyVersion("1.0.0")]
22 |
23 | // The following attributes are used to specify the signing key for the assembly,
24 | // if desired. See the Mono documentation for more information about signing.
25 |
26 | //[assembly: AssemblyDelaySign(false)]
27 | //[assembly: AssemblyKeyFile("")]
28 |
29 |
--------------------------------------------------------------------------------
/iOS/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | LSRequiresIPhoneOS
6 |
7 | MinimumOSVersion
8 | 8.0
9 | UIDeviceFamily
10 |
11 | 1
12 |
13 | UILaunchStoryboardName
14 | LaunchScreen
15 | UIMainStoryboardFile
16 | Main
17 | UIRequiredDeviceCapabilities
18 |
19 | armv7
20 |
21 | UISupportedInterfaceOrientations
22 |
23 | UIInterfaceOrientationPortrait
24 |
25 | XSAppIconAssets
26 | Resources/Images.xcassets/AppIcons.appiconset
27 | UIStatusBarStyle
28 | UIStatusBarStyleLightContent
29 | UIViewControllerBasedStatusBarAppearance
30 |
31 | CFBundleIdentifier
32 | com.company.savethedate
33 | CFBundleDisplayName
34 | Save The Date
35 | CFBundleShortVersionString
36 | 1.0
37 | CFBundleVersion
38 | 1.0
39 |
40 |
41 |
--------------------------------------------------------------------------------
/iOS/Custom Controls/NotifyButton.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using UIKit;
3 | using CoreGraphics;
4 | using Foundation;
5 | using System.ComponentModel;
6 |
7 | namespace SaveTheDate.iOS.CustomControls
8 | {
9 | [Register("NotifyButton"), DesignTimeVisible(true)]
10 | public class NotifyButton : UIButton
11 | {
12 | public NotifyButton(IntPtr handle)
13 | : base(handle)
14 | {
15 | Initialize();
16 | }
17 |
18 | public void Initialize()
19 | {
20 | this.SetTitleColor(UIColor.White, UIControlState.Normal);
21 | this.SetTitleColor(UIColor.FromRGB(73, 96, 134), UIControlState.Disabled);
22 | }
23 |
24 | public override bool Enabled
25 | {
26 | get
27 | {
28 | return base.Enabled;
29 | }
30 | set
31 | {
32 | borderColor = value == true ? UIColor.White.CGColor : UIColor.FromRGB(73, 96, 134).CGColor;
33 | SetNeedsDisplay();
34 | base.Enabled = value;
35 | }
36 | }
37 |
38 | CGColor borderColor = UIColor.White.CGColor;
39 |
40 |
41 | public override void Draw(CoreGraphics.CGRect rect)
42 | {
43 | Layer.BorderColor = borderColor;
44 | Layer.BorderWidth = 1;
45 | Layer.CornerRadius = Frame.Height / 2;
46 | }
47 | }
48 | }
49 |
50 |
--------------------------------------------------------------------------------
/Droid/PluginsHelp/SettingsReadme.txt:
--------------------------------------------------------------------------------
1 | Ensure that you install NuGet into PCL and see Helpers/Settings.cs
2 |
3 | If you are installing this in a normal project and not using a pcl create a new file called Settings.cs or whatever you want and copy this code in:
4 |
5 |
6 | // Helpers/Settings.cs
7 | using Refractored.Xam.Settings;
8 | using Refractored.Xam.Settings.Abstractions;
9 |
10 | namespace SaveTheDate.Droid.Helpers
11 | {
12 | ///
13 | /// This is the Settings static class that can be used in your Core solution or in any
14 | /// of your client applications. All settings are laid out the same exact way with getters
15 | /// and setters.
16 | ///
17 | public static class Settings
18 | {
19 | private static ISettings AppSettings
20 | {
21 | get
22 | {
23 | return CrossSettings.Current;
24 | }
25 | }
26 |
27 | #region Setting Constants
28 |
29 | private const string SettingsKey = "settings_key";
30 | private static readonly string SettingsDefault = string.Empty;
31 |
32 | #endregion
33 |
34 |
35 | public static string GeneralSettings
36 | {
37 | get
38 | {
39 | return AppSettings.GetValueOrDefault(SettingsKey, SettingsDefault);
40 | }
41 | set
42 | {
43 | AppSettings.AddOrUpdateValue(SettingsKey, value);
44 | }
45 | }
46 |
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/iOS/PluginsHelp/SettingsReadme.txt:
--------------------------------------------------------------------------------
1 | Ensure that you install NuGet into PCL and see Helpers/Settings.cs
2 |
3 | If you are installing this in a normal project and not using a pcl create a new file called Settings.cs or whatever you want and copy this code in:
4 |
5 |
6 | // Helpers/Settings.cs
7 | using Refractored.Xam.Settings;
8 | using Refractored.Xam.Settings.Abstractions;
9 |
10 | namespace SaveTheDate.iOS.Helpers
11 | {
12 | ///
13 | /// This is the Settings static class that can be used in your Core solution or in any
14 | /// of your client applications. All settings are laid out the same exact way with getters
15 | /// and setters.
16 | ///
17 | public static class Settings
18 | {
19 | private static ISettings AppSettings
20 | {
21 | get
22 | {
23 | return CrossSettings.Current;
24 | }
25 | }
26 |
27 | #region Setting Constants
28 |
29 | private const string SettingsKey = "settings_key";
30 | private static readonly string SettingsDefault = string.Empty;
31 |
32 | #endregion
33 |
34 |
35 | public static string GeneralSettings
36 | {
37 | get
38 | {
39 | return AppSettings.GetValueOrDefault(SettingsKey, SettingsDefault);
40 | }
41 | set
42 | {
43 | AppSettings.AddOrUpdateValue(SettingsKey, value);
44 | }
45 | }
46 |
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/Droid/Resources/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
31 |
32 |
35 |
--------------------------------------------------------------------------------
/Droid/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.axml),
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/
12 | icon.png
13 |
14 | layout/
15 | main.axml
16 |
17 | values/
18 | strings.xml
19 |
20 | In order to get the build system to recognize Android resources, set the build action to
21 | "AndroidResource". The native Android APIs do not operate directly with filenames, but
22 | instead operate on resource IDs. When you compile an Android application that uses resources,
23 | the build system will package the resources for distribution and generate a class called "R"
24 | (this is an Android convention) that contains the tokens for each one of the resources
25 | included. For example, for the above Resources layout, this is what the R class would expose:
26 |
27 | public class R {
28 | public class drawable {
29 | public const int icon = 0x123;
30 | }
31 |
32 | public class layout {
33 | public const int main = 0x456;
34 | }
35 |
36 | public class strings {
37 | public const int first_string = 0xabc;
38 | public const int second_string = 0xbcd;
39 | }
40 | }
41 |
42 | You would then use R.drawable.icon to reference the drawable/icon.png file, or R.layout.main
43 | to reference the layout/main.axml file, or R.strings.first_string to reference the first
44 | string in the dictionary file values/strings.xml.
45 |
--------------------------------------------------------------------------------
/iOS/Helpers/MessageDialog.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using UIKit;
3 | using SaveTheDate.Interfaces;
4 | using GCDiscreetNotification;
5 |
6 | namespace SaveTheDate.iOS.Helpers
7 | {
8 | public class MessageDialog : IMessage
9 | {
10 |
11 | public void SendMessage(string message, string title = null)
12 | {
13 | Utils.EnsureInvokedOnMainThread(() =>
14 | {
15 | var alertView = new UIAlertView(title ?? string.Empty, message, null, "OK");
16 | alertView.Show();
17 | });
18 | }
19 |
20 |
21 | public void SendToast(string message)
22 | {
23 | Utils.EnsureInvokedOnMainThread(() =>
24 | {
25 | var notificationView = new GCDiscreetNotificationView(
26 | text: message,
27 | activity: false,
28 | presentationMode: GCDNPresentationMode.Bottom,
29 | view: UIApplication.SharedApplication.KeyWindow
30 | );
31 |
32 | notificationView.ShowAndDismissAfter(4);
33 | });
34 | }
35 |
36 | public void SendConfirmation(string message, string title, System.Action confirmationAction)
37 | {
38 | Utils.EnsureInvokedOnMainThread(() =>
39 | {
40 | var alertView = new UIAlertView(title ?? string.Empty, message, null, "OK", "Cancel");
41 | alertView.Clicked += (sender, e) =>
42 | {
43 | confirmationAction(e.ButtonIndex == 0);
44 | };
45 | alertView.Show();
46 | });
47 | }
48 | }
49 | }
50 |
51 |
--------------------------------------------------------------------------------
/UITests/UITests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | {F69E4794-C0E5-441D-BDE3-8D40A18B1E54}
7 | Library
8 | UITests
9 | UITests
10 | v4.5
11 |
12 |
13 | true
14 | full
15 | false
16 | bin\Debug
17 | DEBUG;
18 | prompt
19 | 4
20 | false
21 |
22 |
23 | full
24 | true
25 | bin\Release
26 | prompt
27 | 4
28 | false
29 |
30 |
31 | false
32 | bin\iPhone\AppStore
33 | 4
34 |
35 |
36 |
37 |
38 | ..\packages\Xamarin.UITest.1.0.0\lib\Xamarin.UITest.dll
39 |
40 |
41 | ..\packages\NUnit.2.6.4\lib\nunit.framework.dll
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/iOS/Helpers/ViewExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using UIKit;
3 |
4 | namespace SaveTheDate.iOS.Helpers
5 | {
6 | public static class ViewExtensions
7 | {
8 | ///
9 | /// Find the first responder in the 's subview hierarchy
10 | ///
11 | ///
12 | /// A
13 | ///
14 | ///
15 | /// A that is the first responder or null if there is no first responder
16 | ///
17 | public static UIView FindFirstResponder(this UIView view)
18 | {
19 | if (view.IsFirstResponder)
20 | {
21 | return view;
22 | }
23 | foreach (UIView subView in view.Subviews)
24 | {
25 | var firstResponder = subView.FindFirstResponder();
26 | if (firstResponder != null)
27 | return firstResponder;
28 | }
29 | return null;
30 | }
31 |
32 | ///
33 | /// Find the first Superview of the specified type (or descendant of)
34 | ///
35 | ///
36 | /// A
37 | ///
38 | ///
39 | /// A that indicates where to stop looking up the superview hierarchy
40 | ///
41 | ///
42 | /// A to look for, this should be a UIView or descendant type
43 | ///
44 | ///
45 | /// A if it is found, otherwise null
46 | ///
47 | public static UIView FindSuperviewOfType(this UIView view, UIView stopAt, Type type)
48 | {
49 | if (view.Superview != null)
50 | {
51 | if (type.IsAssignableFrom(view.Superview.GetType()))
52 | {
53 | return view.Superview;
54 | }
55 |
56 | if (view.Superview != stopAt)
57 | return view.Superview.FindSuperviewOfType(stopAt, type);
58 | }
59 |
60 | return null;
61 | }
62 |
63 | }
64 |
65 | }
66 |
67 |
--------------------------------------------------------------------------------
/Droid/Helpers/MessageDialog.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Android.App;
3 | using Android.Widget;
4 | using SaveTheDate.Interfaces;
5 | using Android.Support.Design.Widget;
6 |
7 | namespace SaveTheDate.Droid.Helpers
8 | {
9 | public class MessageDialog : IMessage
10 | {
11 |
12 | public static void SendMessage(Activity activity, string message, string title = null)
13 | {
14 | var builder = new AlertDialog.Builder(activity);
15 | builder
16 | .SetTitle(title ?? string.Empty)
17 | .SetMessage(message)
18 | .SetPositiveButton(Android.Resource.String.Ok, delegate
19 | {
20 |
21 | });
22 |
23 | AlertDialog alert = builder.Create();
24 | alert.Show();
25 | }
26 |
27 | public void SendMessage(string message, string title = null)
28 | {
29 | var activity = AndroidUtils.Context as Activity;
30 | var builder = new AlertDialog.Builder(activity);
31 | builder
32 | .SetTitle(title ?? string.Empty)
33 | .SetMessage(message)
34 | .SetPositiveButton(Android.Resource.String.Ok, delegate
35 | {
36 |
37 | });
38 |
39 | AlertDialog alert = builder.Create();
40 | alert.Show();
41 | }
42 |
43 |
44 | public void SendToast(string message)
45 | {
46 | Snackbar.Make (AndroidUtils.SnackbarView, message, Snackbar.LengthLong)
47 | .SetAction ("OK", (v) => { })
48 | .Show ();
49 |
50 | }
51 |
52 |
53 | public void SendConfirmation(string message, string title, System.Action confirmationAction)
54 | {
55 | var activity = AndroidUtils.Context as Activity;
56 | var builder = new Android.Support.V7.App.AlertDialog.Builder(activity);
57 | builder
58 | .SetTitle(title ?? string.Empty)
59 | .SetMessage(message)
60 | .SetPositiveButton(Android.Resource.String.Ok, delegate
61 | {
62 | confirmationAction(true);
63 | }).SetNegativeButton(Android.Resource.String.Cancel, delegate
64 | {
65 | confirmationAction(false);
66 | });
67 |
68 | var alert = builder.Create();
69 | alert.Show();
70 | }
71 | }
72 | }
73 |
74 |
--------------------------------------------------------------------------------
/SaveTheDate/Helpers/Settings.cs:
--------------------------------------------------------------------------------
1 | // Helpers/Settings.cs
2 | using Refractored.Xam.Settings;
3 | using Refractored.Xam.Settings.Abstractions;
4 |
5 | namespace SaveTheDate.Helpers
6 | {
7 | ///
8 | /// This is the Settings static class that can be used in your Core solution or in any
9 | /// of your client applications. All settings are laid out the same exact way with getters
10 | /// and setters.
11 | ///
12 | public static class Settings
13 | {
14 | static ISettings AppSettings
15 | {
16 | get
17 | {
18 | return CrossSettings.Current;
19 | }
20 | }
21 |
22 | #region Setting Constants
23 |
24 | const string RegisteredKey = "registered_key";
25 | const bool RegisteredDefault = false;
26 | const string RegisteredEmailKey = "registered_email_key";
27 | static readonly string RegisteredEmailDefault = string.Empty;
28 | const string CalendarKey = "calendar_key";
29 | const bool CalendarDefault = false;
30 |
31 | #endregion
32 | public static long GetEventId(string id)
33 | {
34 | return AppSettings.GetValueOrDefault (id, (long)-1);
35 | }
36 |
37 | public static void AddEventId(string id, long eventId)
38 | {
39 | AppSettings.AddOrUpdateValue(id, eventId);
40 | }
41 |
42 | public static bool IsRegistered
43 | {
44 | get
45 | {
46 | return AppSettings.GetValueOrDefault(RegisteredKey, RegisteredDefault);
47 | }
48 | set
49 | {
50 | AppSettings.AddOrUpdateValue(RegisteredKey, value);
51 | }
52 | }
53 |
54 | public static string RegisteredEmail
55 | {
56 | get
57 | {
58 | return AppSettings.GetValueOrDefault(RegisteredEmailKey, RegisteredEmailDefault);
59 | }
60 | set
61 | {
62 | AppSettings.AddOrUpdateValue(RegisteredEmailKey, value);
63 | }
64 | }
65 |
66 | public static bool AddedToCalendar
67 | {
68 | get
69 | {
70 | return AppSettings.GetValueOrDefault(CalendarKey, CalendarDefault);
71 | }
72 | set
73 | {
74 | AppSettings.AddOrUpdateValue(CalendarKey, value);
75 | }
76 | }
77 |
78 | }
79 | }
--------------------------------------------------------------------------------
/SaveTheDate/RegexUtils.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Text.RegularExpressions;
3 |
4 | namespace SaveTheDate
5 | {
6 | public static class RegexUtilities
7 | {
8 |
9 | public static bool IsValidEmail(this string strIn)
10 | {
11 | if (String.IsNullOrEmpty(strIn))
12 | return false;
13 |
14 | // Return true if strIn is in valid e-mail format.
15 | try {
16 | return Regex.IsMatch(strIn,
17 | @"^(?("")("".+?(?\d{3}) # 3 digit area code
37 | (?:[\).]?) # Optional ) or .
38 | (?\d{3}) # Prefix
39 | (?:[-\.]?) # optional - or .
40 | (?\d{4}) # Suffix
41 | (?!\d) # Fail if eleventh number found";
42 |
43 | return Regex.IsMatch(strIn, pattern,RegexOptions.IgnorePatternWhitespace, TimeSpan.FromMilliseconds(250));
44 | }
45 | catch (RegexMatchTimeoutException) {
46 | return false;
47 | }
48 | }
49 |
50 | public static bool IsValidPin(this string strIn)
51 | {
52 | if (String.IsNullOrEmpty(strIn) || strIn.Length != 6)
53 | return false;
54 |
55 | // Return true if strIn is in valid e-mail format.
56 | try {
57 | return Regex.IsMatch(strIn, @"^[0-9]+$",RegexOptions.IgnoreCase, TimeSpan.FromMilliseconds(250));
58 | }
59 | catch (RegexMatchTimeoutException) {
60 | return false;
61 | }
62 | }
63 |
64 | }
65 | }
66 |
67 |
--------------------------------------------------------------------------------
/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 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/iOS/AppDelegate.cs:
--------------------------------------------------------------------------------
1 | using Foundation;
2 | using UIKit;
3 | using SaveTheDate.Helpers;
4 |
5 | namespace SaveTheDate.iOS
6 | {
7 | // The UIApplicationDelegate for the application. This class is responsible for launching the
8 | // User Interface of the application, as well as listening (and optionally responding) to application events from iOS.
9 | [Register("AppDelegate")]
10 | public class AppDelegate : UIApplicationDelegate
11 | {
12 | // class-level declarations
13 |
14 | public override UIWindow Window
15 | {
16 | get;
17 | set;
18 | }
19 |
20 | public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions)
21 | {
22 | // Override point for customization after application launch.
23 | // If not required for your application you can safely delete this method
24 |
25 | //Xamarin.Calabash.Start();
26 |
27 | UIApplication.SharedApplication.SetStatusBarStyle(UIStatusBarStyle.LightContent, false);
28 | Xamarin.Insights.Initialize(Xamarin.Insights.DebugModeKey);
29 | if(!string.IsNullOrWhiteSpace(Settings.RegisteredEmail))
30 | Xamarin.Insights.Identify(Settings.RegisteredEmail, Xamarin.Insights.Traits.Email, Settings.RegisteredEmail);
31 |
32 |
33 | return true;
34 | }
35 |
36 | public override void OnResignActivation(UIApplication application)
37 | {
38 | // Invoked when the application is about to move from active to inactive state.
39 | // This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message)
40 | // or when the user quits the application and it begins the transition to the background state.
41 | // Games should use this method to pause the game.
42 | }
43 |
44 | public override void DidEnterBackground(UIApplication application)
45 | {
46 | // Use this method to release shared resources, save user data, invalidate timers and store the application state.
47 | // If your application supports background exection this method is called instead of WillTerminate when the user quits.
48 | }
49 |
50 | public override void WillEnterForeground(UIApplication application)
51 | {
52 | // Called as part of the transiton from background to active state.
53 | // Here you can undo many of the changes made on entering the background.
54 | }
55 |
56 | public override void OnActivated(UIApplication application)
57 | {
58 | // Restart any tasks that were paused (or not yet started) while the application was inactive.
59 | // If the application was previously in the background, optionally refresh the user interface.
60 | }
61 |
62 | public override void WillTerminate(UIApplication application)
63 | {
64 | // Called when the application is about to terminate. Save data, if needed. See also DidEnterBackground.
65 | }
66 | }
67 | }
68 |
69 |
70 |
--------------------------------------------------------------------------------
/iOS/BaseViewController.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using UIKit;
3 | using Foundation;
4 | using CoreGraphics;
5 | using SaveTheDate.iOS.Helpers;
6 |
7 | namespace SaveTheDate.iOS
8 | {
9 | public class BaseViewController : UIViewController
10 | {
11 | public BaseViewController(IntPtr handle)
12 | : base(handle)
13 | {
14 | }
15 |
16 | #region ManageTheKeyboard
17 |
18 | NSObject _keyboardShowObserver;
19 | NSObject _keyboardHideObserver;
20 |
21 | protected virtual void RegisterForKeyboardNotifications()
22 | {
23 | if (_keyboardShowObserver == null)
24 | _keyboardShowObserver = NSNotificationCenter.DefaultCenter.AddObserver(UIKeyboard.WillShowNotification, OnKeyboardNotification);
25 | if (_keyboardHideObserver == null)
26 | _keyboardHideObserver = NSNotificationCenter.DefaultCenter.AddObserver(UIKeyboard.WillHideNotification, OnKeyboardNotification);
27 | }
28 |
29 | protected virtual void UnregisterForKeyboardNotifications()
30 | {
31 | if (_keyboardShowObserver != null)
32 | {
33 | NSNotificationCenter.DefaultCenter.RemoveObserver(_keyboardShowObserver);
34 | _keyboardShowObserver.Dispose();
35 | _keyboardShowObserver = null;
36 | }
37 |
38 | if (_keyboardHideObserver != null)
39 | {
40 | NSNotificationCenter.DefaultCenter.RemoveObserver(_keyboardHideObserver);
41 | _keyboardHideObserver.Dispose();
42 | _keyboardHideObserver = null;
43 | }
44 | }
45 |
46 | private void OnKeyboardNotification(NSNotification notification)
47 | {
48 | if (!IsViewLoaded)
49 | return;
50 |
51 | //Check if the keyboard is becoming visible
52 | var visible = notification.Name == UIKeyboard.WillShowNotification;
53 |
54 | //Start an animation, using values from the keyboard
55 | UIView.BeginAnimations("AnimateForKeyboard");
56 | UIView.SetAnimationBeginsFromCurrentState(true);
57 | UIView.SetAnimationDuration(UIKeyboard.AnimationDurationFromNotification(notification));
58 | UIView.SetAnimationCurve((UIViewAnimationCurve)UIKeyboard.AnimationCurveFromNotification(notification));
59 |
60 | //Pass the notification, calculating keyboard height, etc.
61 | var keyboardFrame = visible
62 | ? UIKeyboard.FrameEndFromNotification(notification)
63 | : UIKeyboard.FrameBeginFromNotification(notification);
64 |
65 | OnKeyboardChanged(visible, keyboardFrame);
66 |
67 | //Commit the animation
68 | UIView.CommitAnimations();
69 | }
70 |
71 |
72 | public virtual void OnKeyboardChanged(bool visible, CGRect keyboardFrame)
73 | {
74 | //Implement
75 | }
76 |
77 | protected void DismissKeyboardOnBackgroundTap()
78 | {
79 | // Add gesture recognizer to hide keyboard
80 | var tap = new UITapGestureRecognizer { CancelsTouchesInView = false };
81 | tap.AddTarget(() => View.EndEditing(true));
82 | tap.ShouldReceiveTouch = (recognizer, touch) =>
83 | !(touch.View is UIControl || touch.View.FindSuperviewOfType(View, typeof(UITableViewCell)) != null);
84 | View.AddGestureRecognizer(tap);
85 | }
86 |
87 | #endregion
88 | }
89 | }
90 |
91 |
--------------------------------------------------------------------------------
/iOS/ViewController.designer.cs:
--------------------------------------------------------------------------------
1 | // WARNING
2 | //
3 | // This file has been generated automatically by Xamarin Studio from the outlets and
4 | // actions declared in your storyboard file.
5 | // Manual changes to this file will not be maintained.
6 | //
7 | using Foundation;
8 | using System;
9 | using System.CodeDom.Compiler;
10 | using UIKit;
11 |
12 | namespace SaveTheDate.iOS
13 | {
14 | [Register ("ViewController")]
15 | partial class ViewController
16 | {
17 | [Outlet]
18 | UIKit.UIButton Button { get; set; }
19 |
20 | [Outlet]
21 | [GeneratedCode ("iOS Designer", "1.0")]
22 | UIButton btnAddToCalendar { get; set; }
23 |
24 | [Outlet]
25 | [GeneratedCode ("iOS Designer", "1.0")]
26 | SaveTheDate.iOS.CustomControls.NotifyButton btnNotifyMe { get; set; }
27 |
28 | [Outlet]
29 | [GeneratedCode ("iOS Designer", "1.0")]
30 | UIButton btnShare { get; set; }
31 |
32 | [Outlet]
33 | [GeneratedCode ("iOS Designer", "1.0")]
34 | UIView emailView { get; set; }
35 |
36 | [Outlet]
37 | [GeneratedCode ("iOS Designer", "1.0")]
38 | UIImageView imgLogo { get; set; }
39 |
40 | [Outlet]
41 | [GeneratedCode ("iOS Designer", "1.0")]
42 | UILabel lblDate { get; set; }
43 |
44 | [Outlet]
45 | [GeneratedCode ("iOS Designer", "1.0")]
46 | UILabel lblEmail { get; set; }
47 |
48 | [Outlet]
49 | [GeneratedCode ("iOS Designer", "1.0")]
50 | UILabel lblSaveTheDate { get; set; }
51 |
52 | [Outlet]
53 | [GeneratedCode ("iOS Designer", "1.0")]
54 | UIView line { get; set; }
55 |
56 | [Outlet]
57 | [GeneratedCode ("iOS Designer", "1.0")]
58 | UIActivityIndicatorView progressBar { get; set; }
59 |
60 | [Outlet]
61 | [GeneratedCode ("iOS Designer", "1.0")]
62 | UITextField tbxEmailAddress { get; set; }
63 |
64 | [Action ("btnAddToCalendar_TouchUpInside:")]
65 | [GeneratedCode ("iOS Designer", "1.0")]
66 | partial void btnAddToCalendar_TouchUpInside (UIButton sender);
67 |
68 | [Action ("btnNotifyMe_TouchUpInside:")]
69 | [GeneratedCode ("iOS Designer", "1.0")]
70 | partial void btnNotifyMe_TouchUpInside (SaveTheDate.iOS.CustomControls.NotifyButton sender);
71 |
72 | [Action ("btnShare_TouchUpInside:")]
73 | [GeneratedCode ("iOS Designer", "1.0")]
74 | partial void btnShare_TouchUpInside (UIButton sender);
75 |
76 | void ReleaseDesignerOutlets ()
77 | {
78 | if (btnAddToCalendar != null) {
79 | btnAddToCalendar.Dispose ();
80 | btnAddToCalendar = null;
81 | }
82 | if (btnNotifyMe != null) {
83 | btnNotifyMe.Dispose ();
84 | btnNotifyMe = null;
85 | }
86 | if (btnShare != null) {
87 | btnShare.Dispose ();
88 | btnShare = null;
89 | }
90 | if (emailView != null) {
91 | emailView.Dispose ();
92 | emailView = null;
93 | }
94 | if (imgLogo != null) {
95 | imgLogo.Dispose ();
96 | imgLogo = null;
97 | }
98 | if (lblDate != null) {
99 | lblDate.Dispose ();
100 | lblDate = null;
101 | }
102 | if (lblEmail != null) {
103 | lblEmail.Dispose ();
104 | lblEmail = null;
105 | }
106 | if (lblSaveTheDate != null) {
107 | lblSaveTheDate.Dispose ();
108 | lblSaveTheDate = null;
109 | }
110 | if (line != null) {
111 | line.Dispose ();
112 | line = null;
113 | }
114 | if (progressBar != null) {
115 | progressBar.Dispose ();
116 | progressBar = null;
117 | }
118 | if (tbxEmailAddress != null) {
119 | tbxEmailAddress.Dispose ();
120 | tbxEmailAddress = null;
121 | }
122 | }
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/SaveTheDate/SaveTheDateHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading.Tasks;
3 | using System.Net.Http;
4 | using SaveTheDate.Helpers;
5 | using DeviceInfo.Plugin;
6 |
7 | namespace SaveTheDate
8 | {
9 | public static class SaveTheDateHelper
10 | {
11 |
12 | public static void Share()
13 | {
14 | Xamarin.Insights.Track("Share");
15 | Utils.Sharer.ShareText(Strings.ShareText);
16 | }
17 |
18 | public static void AddToCalendar()
19 | {
20 | Xamarin.Insights.Track("AddToCalendar");
21 |
22 | //Start and End dates
23 | var start = new DateTime(2016, 4, 24, 12, 0, 0);
24 | var end = new DateTime(2016, 4, 28, 12, 0, 0);
25 |
26 | Utils.Reminder.AddEvent(start, end, "Your Event Name", "Event Location", string.Empty, (success) =>
27 | {
28 | Settings.AddedToCalendar = success;
29 | if (success)
30 | {
31 | Utils.Message.SendToast("Added to Calendar Successfully");
32 | }
33 | }, "4242016400");
34 | }
35 |
36 | public static bool IsValidEmail(string email)
37 | {
38 | email = email.Trim();
39 | return email.IsValidEmail();
40 | }
41 |
42 |
43 | public static async Task RegisterForNotifications(string email)
44 | {
45 |
46 | var success = false;
47 | try
48 | {
49 |
50 | email = email.Trim();
51 | if (!email.IsValidEmail())
52 | {
53 | Utils.Message.SendToast("Invalid Email Address.");
54 | return false;
55 | }
56 |
57 |
58 | Settings.RegisteredEmail = email;
59 |
60 | Xamarin.Insights.Track("RegisteredForNotifications");
61 | Xamarin.Insights.Identify(Settings.RegisteredEmail, Xamarin.Insights.Traits.Email, Settings.RegisteredEmail);
62 |
63 | //TODO: Implement your backend here
64 | using (var client = new HttpClient())
65 | {
66 | /*var content = new FormUrlEncodedContent(new[]
67 | {
68 | new KeyValuePair("email", email)
69 | });
70 | var result = await client.PostAsync("http://your-post-end-point", content);
71 |
72 | success = result.IsSuccessStatusCode;*/
73 |
74 | success = true;
75 | Settings.IsRegistered = success;
76 | }
77 | }
78 | catch (Exception ex)
79 | {
80 | success = false;
81 | Xamarin.Insights.Report(ex);
82 | }
83 |
84 | var title = "Registration Issue";
85 | var message = "Unable to process, please check your connection.";
86 | if (success)
87 | {
88 | message = "Thanks! You're on the list to be notified about EVENT.";
89 | title = "All Set!";
90 | }
91 |
92 | if (CrossDeviceInfo.Current.Platform == DeviceInfo.Plugin.Abstractions.Platform.iOS)
93 | Utils.Message.SendMessage(message, title);
94 | else
95 | Utils.Message.SendToast(message);
96 |
97 | return success;
98 | }
99 |
100 |
101 | }
102 | }
103 |
104 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | #################
2 | ## Eclipse
3 | #################
4 |
5 | *.pydevproject
6 | .project
7 | .metadata
8 | bin/
9 | tmp/
10 | *.tmp
11 | *.bak
12 | *.swp
13 | *~.nib
14 | local.properties
15 | .classpath
16 | .settings/
17 | .loadpath
18 | mobile.userprefs
19 |
20 | # External tool builders
21 | .externalToolBuilders/
22 |
23 | # Locally stored "Eclipse launch configurations"
24 | *.launch
25 |
26 | # CDT-specific
27 | .cproject
28 |
29 | # PDT-specific
30 | .buildpath
31 |
32 |
33 | #################
34 | ## Visual Studio
35 | #################
36 |
37 | ## Ignore Visual Studio temporary files, build results, and
38 | ## files generated by popular Visual Studio add-ons.
39 |
40 | # User-specific files
41 | *.suo
42 | *.user
43 | *.sln.docstates
44 |
45 | # Build results
46 |
47 | [Dd]ebug/
48 | [Rr]elease/
49 | x64/
50 | build/
51 | [Bb]in/
52 | [Oo]bj/
53 | [Cc]omponents/
54 | [Pp]ackages/
55 |
56 | # MSTest test Results
57 | [Tt]est[Rr]esult*/
58 | [Bb]uild[Ll]og.*
59 |
60 | *_i.c
61 | *_p.c
62 | *.ilk
63 | *.meta
64 | *.obj
65 | *.pch
66 | *.pdb
67 | *.pgc
68 | *.pgd
69 | *.rsp
70 | *.sbr
71 | *.tlb
72 | *.tli
73 | *.tlh
74 | *.tmp
75 | *.tmp_proj
76 | *.log
77 | *.vspscc
78 | *.vssscc
79 | .builds
80 | *.pidb
81 | *.log
82 | *.scc
83 |
84 | # Visual C++ cache files
85 | ipch/
86 | *.aps
87 | *.ncb
88 | *.opensdf
89 | *.sdf
90 | *.cachefile
91 |
92 | # Visual Studio profiler
93 | *.psess
94 | *.vsp
95 | *.vspx
96 |
97 | # Guidance Automation Toolkit
98 | *.gpState
99 |
100 | # ReSharper is a .NET coding add-in
101 | _ReSharper*/
102 | *.[Rr]e[Ss]harper
103 |
104 | # TeamCity is a build add-in
105 | _TeamCity*
106 |
107 | # DotCover is a Code Coverage Tool
108 | *.dotCover
109 |
110 | # NCrunch
111 | *.ncrunch*
112 | .*crunch*.local.xml
113 |
114 | # Installshield output folder
115 | [Ee]xpress/
116 |
117 | # DocProject is a documentation generator add-in
118 | DocProject/buildhelp/
119 | DocProject/Help/*.HxT
120 | DocProject/Help/*.HxC
121 | DocProject/Help/*.hhc
122 | DocProject/Help/*.hhk
123 | DocProject/Help/*.hhp
124 | DocProject/Help/Html2
125 | DocProject/Help/html
126 |
127 | # Click-Once directory
128 | publish/
129 |
130 | # Publish Web Output
131 | *.Publish.xml
132 | *.pubxml
133 |
134 | # NuGet Packages Directory
135 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line
136 | #packages/
137 |
138 | # Windows Azure Build Output
139 | csx
140 | *.build.csdef
141 |
142 | # Windows Store app package directory
143 | AppPackages/
144 |
145 | # Others
146 | sql/
147 | *.Cache
148 | ClientBin/
149 | [Ss]tyle[Cc]op.*
150 | ~$*
151 | *~
152 | *.dbmdl
153 | *.[Pp]ublish.xml
154 | *.pfx
155 | *.publishsettings
156 |
157 | # RIA/Silverlight projects
158 | Generated_Code/
159 |
160 | # Backup & report files from converting an old project file to a newer
161 | # Visual Studio version. Backup files are not needed, because we have git ;-)
162 | _UpgradeReport_Files/
163 | Backup*/
164 | UpgradeLog*.XML
165 | UpgradeLog*.htm
166 |
167 | # SQL Server files
168 | App_Data/*.mdf
169 | App_Data/*.ldf
170 |
171 | #############
172 | ## Windows detritus
173 | #############
174 |
175 | # Windows image file caches
176 | Thumbs.db
177 | ehthumbs.db
178 |
179 | # Folder config file
180 | Desktop.ini
181 |
182 | # Recycle Bin used on file shares
183 | $RECYCLE.BIN/
184 |
185 | # Mac crap
186 | .DS_Store
187 |
188 | #############
189 | Git
190 | #############
191 |
192 | *.orig
193 |
194 | #############
195 | ## Python
196 | #############
197 |
198 | *.py[co]
199 |
200 | # Packages
201 | *.egg
202 | *.egg-info
203 | dist/
204 | build/
205 | eggs/
206 | parts/
207 | var/
208 | sdist/
209 | develop-eggs/
210 | .installed.cfg
211 |
212 | # Installer logs
213 | pip-log.txt
214 |
215 | # Unit test / coverage reports
216 | .coverage
217 | .tox
218 |
219 | #Translations
220 | *.mo
221 |
222 | #Mr Developer
223 | .mr.developer.cfg
224 |
225 | XamarinEvolve.userprefs
226 |
--------------------------------------------------------------------------------
/iOS/Resources/Images.xcassets/AppIcons.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images": [
3 | {
4 | "filename": "Icon-Settings.png",
5 | "size": "29x29",
6 | "scale": "1x",
7 | "idiom": "iphone"
8 | },
9 | {
10 | "filename": "Icon-Settings@2x.png",
11 | "size": "29x29",
12 | "scale": "2x",
13 | "idiom": "iphone"
14 | },
15 | {
16 | "filename": "Icon-Settings@3x.png",
17 | "size": "29x29",
18 | "scale": "3x",
19 | "idiom": "iphone"
20 | },
21 | {
22 | "filename": "Icon-Small@2x.png",
23 | "size": "40x40",
24 | "scale": "2x",
25 | "idiom": "iphone"
26 | },
27 | {
28 | "filename": "Icon-Small@3x.png",
29 | "size": "40x40",
30 | "scale": "3x",
31 | "idiom": "iphone"
32 | },
33 | {
34 | "size": "57x57",
35 | "scale": "1x",
36 | "idiom": "iphone"
37 | },
38 | {
39 | "size": "57x57",
40 | "scale": "2x",
41 | "idiom": "iphone"
42 | },
43 | {
44 | "filename": "Icon@2x.png",
45 | "size": "60x60",
46 | "scale": "2x",
47 | "idiom": "iphone"
48 | },
49 | {
50 | "filename": "Icon@3x.png",
51 | "size": "60x60",
52 | "scale": "3x",
53 | "idiom": "iphone"
54 | },
55 | {
56 | "size": "29x29",
57 | "scale": "1x",
58 | "idiom": "ipad"
59 | },
60 | {
61 | "size": "29x29",
62 | "scale": "2x",
63 | "idiom": "ipad"
64 | },
65 | {
66 | "size": "40x40",
67 | "scale": "1x",
68 | "idiom": "ipad"
69 | },
70 | {
71 | "size": "40x40",
72 | "scale": "2x",
73 | "idiom": "ipad"
74 | },
75 | {
76 | "size": "50x50",
77 | "scale": "1x",
78 | "idiom": "ipad"
79 | },
80 | {
81 | "size": "50x50",
82 | "scale": "2x",
83 | "idiom": "ipad"
84 | },
85 | {
86 | "size": "72x72",
87 | "scale": "1x",
88 | "idiom": "ipad"
89 | },
90 | {
91 | "size": "72x72",
92 | "scale": "2x",
93 | "idiom": "ipad"
94 | },
95 | {
96 | "size": "76x76",
97 | "scale": "1x",
98 | "idiom": "ipad"
99 | },
100 | {
101 | "size": "76x76",
102 | "scale": "2x",
103 | "idiom": "ipad"
104 | },
105 | {
106 | "role": "notificationCenter",
107 | "size": "24x24",
108 | "subtype": "38mm",
109 | "scale": "2x",
110 | "idiom": "watch"
111 | },
112 | {
113 | "role": "notificationCenter",
114 | "size": "27.5x27.5",
115 | "subtype": "42mm",
116 | "scale": "2x",
117 | "idiom": "watch"
118 | },
119 | {
120 | "role": "companionSettings",
121 | "size": "29x29",
122 | "scale": "2x",
123 | "idiom": "watch"
124 | },
125 | {
126 | "role": "companionSettings",
127 | "size": "29x29",
128 | "scale": "3x",
129 | "idiom": "watch"
130 | },
131 | {
132 | "role": "appLauncher",
133 | "size": "40x40",
134 | "subtype": "38mm",
135 | "scale": "2x",
136 | "idiom": "watch"
137 | },
138 | {
139 | "role": "longLook",
140 | "size": "44x44",
141 | "subtype": "42mm",
142 | "scale": "2x",
143 | "idiom": "watch"
144 | },
145 | {
146 | "role": "quickLook",
147 | "size": "86x86",
148 | "subtype": "38mm",
149 | "scale": "2x",
150 | "idiom": "watch"
151 | },
152 | {
153 | "role": "quickLook",
154 | "size": "98x98",
155 | "subtype": "42mm",
156 | "scale": "2x",
157 | "idiom": "watch"
158 | },
159 | {
160 | "size": "120x120",
161 | "scale": "1x",
162 | "idiom": "car"
163 | }
164 | ],
165 | "info": {
166 | "version": 1,
167 | "author": "xcode"
168 | },
169 | "properties": {
170 | "pre-rendered": true
171 | }
172 | }
--------------------------------------------------------------------------------
/Droid/MainActivity.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | using Android.App;
4 | using Android.Content;
5 | using Android.Runtime;
6 | using Android.Views;
7 | using Android.Widget;
8 | using Android.OS;
9 | using SaveTheDate.Droid.Helpers;
10 | using Android.Support.Design.Widget;
11 | using SaveTheDate.Helpers;
12 | using Android.Support.V7.App;
13 |
14 | namespace SaveTheDate.Droid
15 | {
16 | [Activity(Label = "Save The Date", MainLauncher = true, Icon = "@drawable/ic_launcher", ScreenOrientation = Android.Content.PM.ScreenOrientation.Portrait)]
17 | public class MainActivity : AppCompatActivity
18 | {
19 |
20 | protected override void OnCreate(Bundle bundle)
21 | {
22 | base.OnCreate(bundle);
23 |
24 | // Set our view from the "main" layout resource
25 | SetContentView(Resource.Layout.Main);
26 |
27 | Xamarin.Insights.Initialize(Xamarin.Insights.DebugModeKey, this);
28 | if(!string.IsNullOrWhiteSpace(Settings.RegisteredEmail))
29 | Xamarin.Insights.Identify(Settings.RegisteredEmail, Xamarin.Insights.Traits.Email, Settings.RegisteredEmail);
30 |
31 |
32 | Utils.Sharer = new Share();
33 | Utils.Reminder = new ReminderService();
34 | Utils.Message = new MessageDialog();
35 |
36 | AndroidUtils.SnackbarView = FindViewById(Resource.Id.main);
37 | AndroidUtils.Context = this;
38 |
39 | var email = FindViewById(Resource.Id.text_email);
40 | var notify = FindViewById