84ba78a1c5
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>
123 lines
4.0 KiB
C#
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);
|
|
}
|
|
}
|
|
}
|