Files
starface-outlook-sync-addin/src/StarfaceOutlookSync/Services/ProfileManager.cs
T
duffyduck 84ba78a1c5 Rewrite as standalone C# WinForms app
Replace the Office Web Add-in with a native Windows application.
The web add-in required Exchange/M365 for registration which is
not available in all customer environments (standalone Office,
POP/IMAP only).

The new app:
- Uses COM Interop to access Outlook contacts directly
- Communicates with Starface REST API (accepts self-signed certs)
- Runs as System Tray app with optional auto-sync
- Profile-based config stored in %AppData%
- No webserver, no certificates, no Exchange, no M365 needed
- Inno Setup installer for clean MSI-style deployment
- Works with any Outlook version (Classic and New)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 10:26:58 +02:00

123 lines
4.0 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Newtonsoft.Json;
using StarfaceOutlookSync.Models;
namespace StarfaceOutlookSync.Services
{
public class ProfileManager
{
private readonly string _dataDir;
private readonly string _profilesFile;
private readonly string _mappingsDir;
public ProfileManager()
{
_dataDir = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
"StarfaceOutlookSync");
_mappingsDir = Path.Combine(_dataDir, "mappings");
_profilesFile = Path.Combine(_dataDir, "profiles.json");
Directory.CreateDirectory(_dataDir);
Directory.CreateDirectory(_mappingsDir);
}
public List<SyncProfile> GetProfiles()
{
try
{
if (!File.Exists(_profilesFile)) return new List<SyncProfile>();
var json = File.ReadAllText(_profilesFile);
return JsonConvert.DeserializeObject<List<SyncProfile>>(json) ?? new List<SyncProfile>();
}
catch { return new List<SyncProfile>(); }
}
public void SaveProfiles(List<SyncProfile> profiles)
{
var json = JsonConvert.SerializeObject(profiles, Formatting.Indented);
File.WriteAllText(_profilesFile, json);
}
public SyncProfile GetProfile(string id)
{
return GetProfiles().FirstOrDefault(p => p.Id == id);
}
public void AddProfile(SyncProfile profile)
{
var profiles = GetProfiles();
profiles.Add(profile);
SaveProfiles(profiles);
}
public void UpdateProfile(SyncProfile profile)
{
var profiles = GetProfiles();
var idx = profiles.FindIndex(p => p.Id == profile.Id);
if (idx >= 0)
{
profiles[idx] = profile;
SaveProfiles(profiles);
}
}
public void DeleteProfile(string id)
{
var profiles = GetProfiles().Where(p => p.Id != id).ToList();
SaveProfiles(profiles);
var mappingFile = Path.Combine(_mappingsDir, $"{id}.json");
if (File.Exists(mappingFile)) File.Delete(mappingFile);
}
public void UpdateLastSync(string profileId)
{
var profiles = GetProfiles();
var profile = profiles.FirstOrDefault(p => p.Id == profileId);
if (profile != null)
{
profile.LastSync = DateTime.Now.ToString("o");
SaveProfiles(profiles);
}
}
public List<SyncMapping> GetMappings(string profileId)
{
try
{
var file = Path.Combine(_mappingsDir, $"{profileId}.json");
if (!File.Exists(file)) return new List<SyncMapping>();
return JsonConvert.DeserializeObject<List<SyncMapping>>(File.ReadAllText(file))
?? new List<SyncMapping>();
}
catch { return new List<SyncMapping>(); }
}
public void SaveMappings(string profileId, List<SyncMapping> mappings)
{
var file = Path.Combine(_mappingsDir, $"{profileId}.json");
File.WriteAllText(file, JsonConvert.SerializeObject(mappings, Formatting.Indented));
}
public void AddOrUpdateMapping(SyncMapping mapping)
{
var mappings = GetMappings(mapping.ProfileId);
var existing = mappings.FindIndex(m =>
m.OutlookEntryId == mapping.OutlookEntryId || m.StarfaceId == mapping.StarfaceId);
if (existing >= 0)
mappings[existing] = mapping;
else
mappings.Add(mapping);
SaveMappings(mapping.ProfileId, mappings);
}
public string GenerateId()
{
return DateTime.Now.Ticks.ToString("x") + Guid.NewGuid().ToString("N").Substring(0, 8);
}
}
}