Open svandelaarschot opened 8 years ago
Trying to help where i can :) so im looking to get the project running :) and build.
Hi! Thanks for your help!
So, saying that you're referencing "Calendar.Plugin.dll" is actually kind of vague, as there are a few of those. This uses the "PCL Bait & Switch" technique (searching for that term will turn up some explanations, but it's also the standard technique used by almost all Xamarin Plugins).
Basically, that error is because you are referencing the PCL stub class directly, when you actually need to be referencing the platform-specific versions. If you look at the unit test projects, you can see that they just reference the platform-specific projects directly. When installing via NuGet, it automatically takes care of this for you.
Since you mention Portable Forms and are trying to work on this, I'm guessing that you're trying to reference the projects directly from a Xamarin.Forms projects so you can test and debug into them? In which case I believe you can reference Calendars.Plugin from Portable Forms, but then in the iOS/Android projects reference the .Android/.iOSUnified versions instead.
You still want the Abstractions referenced by everything, there are no tricks to that one.
Also, it seemed from a previous message like you had tried just adding the calendar to the Exchange source as part of the existing logic, but decided that it didn't work? I didn't quite follow what the problem was there.
You suggest to "Let the people on iOS choose the source they want." I'm open to such an idea in cases where the iOS Calendar app would actually display multiple "Add Calendar" buttons for different sources, but I wouldn't want to offer a choice of "Local" if that's only going to result in a hidden calendar...
Hey Caleb, Yes today i was struggeling with the plugin since i need it @t my work for the waste management APP people going to put their waste collection days into the native calendar.
Someone came up and asked me why they can't see the events into their 'Account' because they had multiple exchange accounts on their iPad.
So we need to find a way that the user can select their own 'Agenda' / 'Account'.
Its weird from apple if you look at the Android version of the Plugin it just creates a new account into they Calendar itselfs wich is nice. and understandable. compared to iOS
So is it successfully adding the calendar to one of those exchange accounts, and the problem is that it's choosing the "wrong" one?
Or is it failing to add the calendar to either account?
And yes this is an annoying undocumented quirk of iOS...
Im making a Xamarin.Forms version of yours :) keep ya up to date.
FIXED ! Always assign the calendar in CalendarSource: Subscribed Calendars and the problem with hidden calendars is gone.
Caleb,
Create a property in Asbtractions.Calendar
/// <summary>
/// The Account of the calendar
/// </summary>
public String Source { get; set; }
and when its filled with "Subscribed Calendars" for example than take source: Subscribed Calendars else do your loops through source :)
public async Task AddOrUpdateCalendarAsync(Calendar calendar)
{
InitEventStore();
await RequestCalendarAccess().ConfigureAwait(false);
EKCalendar deviceCalendar = null;
EKSource Source = null;
if(!String.IsNullOrEmpty(calendar.Identifier))
{
deviceCalendar = _eventStore.GetCalendar(calendar.Identifier);
if (!String.IsNullOrEmpty(calendar.Source))
{
/* Going for the save way ! */
foreach (var item in _eventStore.Sources)
{
if (item.Title == calendar.Source)
{
Source = item;
break;
}
}
}
deviceCalendar.Source = Source;
if (deviceCalendar == null)
{
throw new ArgumentException("Specified calendar does not exist on device", nameof(calendar));
}
}
if (deviceCalendar == null)
{
if (!String.IsNullOrEmpty(calendar.Source))
{
/* Going for the save way ! */
foreach (var item in _eventStore.Sources)
{
if (item.Title == calendar.Source)
{
Source = item;
break;
}
}
}
deviceCalendar = CreateEKCalendar(calendar.Title, calendar.Color, Source);
deviceCalendar.Source = Source;
calendar.Identifier = deviceCalendar.CalendarIdentifier;
// Update color in case iOS assigned one
if (deviceCalendar?.CGColor != null)
{ calendar.Color = ColorConversion.ToHexColor(deviceCalendar.CGColor); }
}
else
{
deviceCalendar.Title = calendar.Title;
if (!string.IsNullOrEmpty(calendar.Color))
{
deviceCalendar.CGColor = ColorConversion.ToCGColor(calendar.Color);
}
NSError error = null;
if (!_eventStore.SaveCalendar(deviceCalendar, true, out error))
{
// Without this, the eventStore will continue to return the "updated"
// calendar even though the save failed!
// (this obviously also resets any other changes, but since we own the eventStore
// we can be pretty confident that won't be an issue)
//
_eventStore.Reset();
if (error.Domain == _ekErrorDomain && error.Code == (int)EKErrorCode.CalendarIsImmutable)
{
throw new ArgumentException(error.LocalizedDescription, new NSErrorException(error));
}
else
{
throw new PlatformException(error.LocalizedDescription, new NSErrorException(error));
}
}
}
}
` private EKCalendar CreateEKCalendar(string calendarName, string color = null, EKSource Source = null)
{
// Log the available sources
//
System.Console.WriteLine("Sources:");
foreach (var source in _eventStore.Sources)
{
System.Console.WriteLine($"{source.Title}, {source.SourceType}");
}
if (Source == null)
{
// first attempt to find any and all iCloud sources
//
var iCloudSources = _eventStore.Sources.Where(s => s.SourceType == EKSourceType.CalDav &&
s.Title.Equals("icloud", StringComparison.InvariantCultureIgnoreCase));
var cal = SaveEKCalendar(iCloudSources, calendarName, color);
if (cal != null)
{
return cal;
}
// other sources that we didn't try before that are CalDav
// (may be renamed iCloud)
//
var otherSources = _eventStore.Sources.Where(s => s.SourceType == EKSourceType.CalDav &&
!s.Title.Equals("icloud", StringComparison.InvariantCultureIgnoreCase));
cal = SaveEKCalendar(otherSources, calendarName, color);
if (cal != null)
{
return cal;
}
// finally attempt just local sources
//
var localSources = _eventStore.Sources.Where(s => s.SourceType == EKSourceType.Local);
cal = SaveEKCalendar(localSources, calendarName, color, true);
if (cal != null)
{
return cal;
}
}
else
{
var cal = SaveEKCalendar(Source, calendarName, color);
if (cal != null)
{
return cal;
}
}
throw new InvalidOperationException("No active calendar sources available to create calendar on.");
}
`
Maybe some code cleanups after trying :) to make it nice :)
Caleb,
Can you add above code to your code and place it on nuget ? than we have it crossplatform
the property:
/// <summary>
/// The Account of the calendar
/// </summary>
public String Source { get; set; }
Can best be named iOSSource since its ios only behaviour
Kind Regards, Stefan.
Thanks Stefan.
The source Property for Calendars.cs is because you can choose out of exchange accounts or Subscribed calendars but for most of the time Subscribed calendars is the better way to go.
Param for AddOrUpdateCalendar can be but than you need to know the source.
i will try to make a pull request,
I cant make pull requests since you dont gief me the rights i think
You can make pull requests. You can't directly push changes to this repo. You need to create a fork in GitHub, commit your changes there.
Why is Subscribed the better way to go?
i tried to fix it but i don't understood the project .SLN since when i reference the 2 dll files Calendar.Plugin.dll and Calendars.Plugin.Abstractions.dll to every project Portable Forms, Android, iOS i got the error message:
from CrossCalendars.cs
i want to contribute but how does it work? since i can only make it work when installing on nuget.
Idea of the FIX:
Let the people on iOS choose the source they want like Exchange, Local or iCloud