Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 724beba34a | |||
| 65d3e911d0 | |||
| ab9c16c69a | |||
| 3e22a40e17 | |||
| 36aca2c04d | |||
| 4f56f28ccb | |||
| 2b9ad5bf3c | |||
| 8a316600b5 |
+1
-1
@@ -2,7 +2,7 @@
|
||||
; Erfordert Inno Setup 6.x (https://jrsoftware.org/isinfo.php)
|
||||
|
||||
#define MyAppName "Starface Outlook Sync"
|
||||
#define MyAppVersion "0.0.0.13"
|
||||
#define MyAppVersion "0.0.0.16"
|
||||
#define MyAppPublisher "HackerSoft - Hacker-Net Telekommunikation"
|
||||
#define MyAppURL "https://www.hacker-net.de"
|
||||
#define MyAppExeName "StarfaceOutlookSync.exe"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Security.Cryptography;
|
||||
@@ -115,43 +116,63 @@ namespace StarfaceOutlookSync.Services
|
||||
{
|
||||
var books = new List<StarfaceAddressBook>();
|
||||
|
||||
books.Add(new StarfaceAddressBook
|
||||
{
|
||||
Type = "central",
|
||||
Name = "Zentrales Adressbuch"
|
||||
});
|
||||
|
||||
var userId = await GetCurrentUserIdAsync();
|
||||
if (!string.IsNullOrEmpty(userId))
|
||||
{
|
||||
books.Add(new StarfaceAddressBook
|
||||
{
|
||||
Type = "user",
|
||||
UserId = userId,
|
||||
Name = "Persoenliches Adressbuch"
|
||||
});
|
||||
}
|
||||
|
||||
// Tags als virtuelle Adressbuecher
|
||||
// Alle Tags laden - die Starface nutzt Tags als Adressbuch-Zuordnung
|
||||
var allTags = new JArray();
|
||||
try
|
||||
{
|
||||
var resp = await _http.GetAsync($"{_baseUrl}/contacts/tags");
|
||||
if (resp.IsSuccessStatusCode)
|
||||
{
|
||||
var tags = JArray.Parse(await resp.Content.ReadAsStringAsync());
|
||||
foreach (var tag in tags)
|
||||
{
|
||||
books.Add(new StarfaceAddressBook
|
||||
{
|
||||
Type = "tag",
|
||||
TagId = tag["id"]?.ToString() ?? "",
|
||||
Name = $"Tag: {tag["name"]}"
|
||||
});
|
||||
}
|
||||
allTags = JArray.Parse(await resp.Content.ReadAsStringAsync());
|
||||
OnDebug?.Invoke($"Gefundene Tags: {allTags.Count}");
|
||||
foreach (var t in allTags)
|
||||
OnDebug?.Invoke($" Tag: {t["name"]} (id: {t["id"]}, alias: {t["alias"]}, owner: {t["owner"]})");
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
// Zentrales Adressbuch (folder/all)
|
||||
var allTag = allTags.FirstOrDefault(t => t["name"]?.ToString() == "folder/all"
|
||||
|| t["alias"]?.ToString()?.Contains("folder.all") == true);
|
||||
books.Add(new StarfaceAddressBook
|
||||
{
|
||||
Type = "central",
|
||||
TagId = allTag?["id"]?.ToString() ?? "",
|
||||
Name = "Zentrales Adressbuch"
|
||||
});
|
||||
|
||||
// Persoenliches Adressbuch (folder/private mit owner = userId)
|
||||
var userId = await GetCurrentUserIdAsync();
|
||||
if (!string.IsNullOrEmpty(userId))
|
||||
{
|
||||
var privateTag = allTags.FirstOrDefault(t =>
|
||||
(t["name"]?.ToString() == "folder/private" || t["alias"]?.ToString()?.Contains("folder.private") == true)
|
||||
&& t["owner"]?.ToString() == userId);
|
||||
|
||||
books.Add(new StarfaceAddressBook
|
||||
{
|
||||
Type = "user",
|
||||
UserId = userId,
|
||||
TagId = privateTag?["id"]?.ToString() ?? "",
|
||||
Name = "Persoenliches Adressbuch"
|
||||
});
|
||||
}
|
||||
|
||||
// Alle weiteren Tags als Adressbuecher anbieten
|
||||
foreach (var tag in allTags)
|
||||
{
|
||||
var tagName = tag["name"]?.ToString() ?? "";
|
||||
// folder/all und folder/private bereits oben erfasst
|
||||
if (tagName == "folder/all" || tagName == "folder/private") continue;
|
||||
|
||||
books.Add(new StarfaceAddressBook
|
||||
{
|
||||
Type = "tag",
|
||||
TagId = tag["id"]?.ToString() ?? "",
|
||||
Name = tagName
|
||||
});
|
||||
}
|
||||
|
||||
return books;
|
||||
}
|
||||
|
||||
@@ -248,15 +269,34 @@ namespace StarfaceOutlookSync.Services
|
||||
public async Task<UnifiedContact> CreateContactAsync(UnifiedContact contact, StarfaceAddressBook book)
|
||||
{
|
||||
var sfContact = MapToStarface(contact);
|
||||
|
||||
// Tag zuweisen - die Starface verlangt dass jeder Kontakt einem Tag zugeordnet ist
|
||||
if (!string.IsNullOrEmpty(book.TagId))
|
||||
{
|
||||
sfContact["tags"] = new JArray
|
||||
{
|
||||
new JObject { ["id"] = book.TagId }
|
||||
};
|
||||
}
|
||||
|
||||
var query = "";
|
||||
if (book.Type == "user" && !string.IsNullOrEmpty(book.UserId))
|
||||
query = $"?userId={book.UserId}";
|
||||
|
||||
var content = new StringContent(sfContact.ToString(), Encoding.UTF8, "application/json");
|
||||
var resp = await _http.PostAsync($"{_baseUrl}/contacts{query}", content);
|
||||
if (!resp.IsSuccessStatusCode) return null;
|
||||
var body = sfContact.ToString();
|
||||
OnDebug?.Invoke($"POST /contacts{query} Body:\n{body}");
|
||||
|
||||
var created = JObject.Parse(await resp.Content.ReadAsStringAsync());
|
||||
var content = new StringContent(body, Encoding.UTF8, "application/json");
|
||||
var resp = await _http.PostAsync($"{_baseUrl}/contacts{query}", content);
|
||||
var respBody = await resp.Content.ReadAsStringAsync();
|
||||
|
||||
if (!resp.IsSuccessStatusCode)
|
||||
{
|
||||
OnDebug?.Invoke($"POST /contacts fehlgeschlagen: {(int)resp.StatusCode} {resp.StatusCode}\n{respBody}");
|
||||
return null;
|
||||
}
|
||||
|
||||
var created = JObject.Parse(respBody);
|
||||
return MapFromStarface(created);
|
||||
}
|
||||
|
||||
|
||||
@@ -247,6 +247,7 @@ namespace StarfaceOutlookSync.Services
|
||||
else
|
||||
{
|
||||
// Neu -> in Starface erstellen
|
||||
Log($" Erstelle in Starface: {oc.DisplayName}");
|
||||
var created = await starface.CreateContactAsync(oc, profile.StarfaceAddressBook);
|
||||
if (created != null && !string.IsNullOrEmpty(created.StarfaceId))
|
||||
{
|
||||
@@ -260,6 +261,11 @@ namespace StarfaceOutlookSync.Services
|
||||
result.Created++;
|
||||
Log($" Erstellt (OL->SF): {oc.DisplayName}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Log($" FEHLER: Kontakt konnte nicht erstellt werden: {oc.DisplayName}");
|
||||
result.Errors++;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
<AssemblyTitle>Starface Outlook Sync</AssemblyTitle>
|
||||
<Company>HackerSoft - Hacker-Net Telekommunikation</Company>
|
||||
<Product>Starface Outlook Sync</Product>
|
||||
<Version>0.0.0.13</Version>
|
||||
<AssemblyVersion>0.0.0.13</AssemblyVersion>
|
||||
<FileVersion>0.0.0.13</FileVersion>
|
||||
<Version>0.0.0.16</Version>
|
||||
<AssemblyVersion>0.0.0.16</AssemblyVersion>
|
||||
<FileVersion>0.0.0.16</FileVersion>
|
||||
<Description>Synchronisiert Outlook-Kontakte mit Starface Telefonanlage</Description>
|
||||
<Copyright>Stefan Hacker - HackerSoft</Copyright>
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace StarfaceOutlookSync.UI
|
||||
|
||||
var lblVersion = new Label
|
||||
{
|
||||
Text = "Version 0.0.0.13",
|
||||
Text = "Version 0.0.0.16",
|
||||
Left = 0, Top = 56, Width = 340, Height = 20,
|
||||
TextAlign = ContentAlignment.MiddleCenter,
|
||||
ForeColor = Color.Gray
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
|
||||
namespace StarfaceOutlookSync.UI
|
||||
{
|
||||
/// <summary>
|
||||
/// Generiert das App-Icon programmatisch (Kontakt-Symbol mit Sync-Pfeilen).
|
||||
/// Kein externes ICO-File noetig.
|
||||
/// </summary>
|
||||
public static class AppIcon
|
||||
{
|
||||
private static Icon _icon;
|
||||
|
||||
public static Icon GetIcon()
|
||||
{
|
||||
if (_icon != null) return _icon;
|
||||
_icon = CreateIcon(32);
|
||||
return _icon;
|
||||
}
|
||||
|
||||
public static Icon GetSmallIcon()
|
||||
{
|
||||
return CreateIcon(16);
|
||||
}
|
||||
|
||||
private static Icon CreateIcon(int size)
|
||||
{
|
||||
using (var bmp = new Bitmap(size, size))
|
||||
using (var g = Graphics.FromImage(bmp))
|
||||
{
|
||||
g.SmoothingMode = SmoothingMode.AntiAlias;
|
||||
g.Clear(Color.Transparent);
|
||||
|
||||
if (size >= 32)
|
||||
DrawIcon32(g);
|
||||
else
|
||||
DrawIcon16(g);
|
||||
|
||||
return Icon.FromHandle(bmp.GetHicon());
|
||||
}
|
||||
}
|
||||
|
||||
private static void DrawIcon32(Graphics g)
|
||||
{
|
||||
// Hintergrund: abgerundetes Quadrat
|
||||
using (var bgBrush = new SolidBrush(Color.FromArgb(0, 120, 212)))
|
||||
{
|
||||
FillRoundedRect(g, bgBrush, 0, 0, 31, 31, 6);
|
||||
}
|
||||
|
||||
// Person (Kopf)
|
||||
using (var whiteBrush = new SolidBrush(Color.White))
|
||||
{
|
||||
g.FillEllipse(whiteBrush, 11, 4, 10, 10);
|
||||
// Person (Koerper)
|
||||
g.FillPie(whiteBrush, 6, 14, 20, 18, 180, 180);
|
||||
}
|
||||
|
||||
// Sync-Pfeile unten rechts
|
||||
using (var arrowPen = new Pen(Color.FromArgb(120, 255, 120), 2f))
|
||||
{
|
||||
arrowPen.StartCap = LineCap.Round;
|
||||
arrowPen.EndCap = LineCap.ArrowAnchor;
|
||||
// Pfeil rechts
|
||||
g.DrawArc(arrowPen, 20, 22, 10, 8, 200, 140);
|
||||
arrowPen.Color = Color.FromArgb(255, 200, 80);
|
||||
// Pfeil links
|
||||
g.DrawArc(arrowPen, 20, 22, 10, 8, 20, 140);
|
||||
}
|
||||
}
|
||||
|
||||
private static void DrawIcon16(Graphics g)
|
||||
{
|
||||
// Hintergrund
|
||||
using (var bgBrush = new SolidBrush(Color.FromArgb(0, 120, 212)))
|
||||
{
|
||||
FillRoundedRect(g, bgBrush, 0, 0, 15, 15, 3);
|
||||
}
|
||||
|
||||
// Person (vereinfacht)
|
||||
using (var whiteBrush = new SolidBrush(Color.White))
|
||||
{
|
||||
g.FillEllipse(whiteBrush, 4, 1, 7, 7);
|
||||
g.FillPie(whiteBrush, 2, 8, 12, 10, 180, 180);
|
||||
}
|
||||
|
||||
// Kleiner Sync-Indikator
|
||||
using (var dotBrush = new SolidBrush(Color.FromArgb(120, 255, 120)))
|
||||
{
|
||||
g.FillEllipse(dotBrush, 11, 11, 4, 4);
|
||||
}
|
||||
}
|
||||
|
||||
private static void FillRoundedRect(Graphics g, Brush brush, int x, int y, int w, int h, int r)
|
||||
{
|
||||
using (var path = new GraphicsPath())
|
||||
{
|
||||
path.AddArc(x, y, r * 2, r * 2, 180, 90);
|
||||
path.AddArc(x + w - r * 2, y, r * 2, r * 2, 270, 90);
|
||||
path.AddArc(x + w - r * 2, y + h - r * 2, r * 2, r * 2, 0, 90);
|
||||
path.AddArc(x, y + h - r * 2, r * 2, r * 2, 90, 90);
|
||||
path.CloseFigure();
|
||||
g.FillPath(brush, path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -62,6 +62,7 @@ namespace StarfaceOutlookSync.UI
|
||||
MinimumSize = new Size(500, 350);
|
||||
StartPosition = FormStartPosition.CenterScreen;
|
||||
Font = new Font("Segoe UI", 9);
|
||||
Icon = AppIcon.GetIcon();
|
||||
|
||||
// Profil-Liste
|
||||
_profileList = new ListView
|
||||
@@ -124,10 +125,26 @@ namespace StarfaceOutlookSync.UI
|
||||
private void SetupTrayIcon()
|
||||
{
|
||||
_trayMenu = new ContextMenuStrip();
|
||||
|
||||
_trayIcon = new NotifyIcon
|
||||
{
|
||||
Text = "Starface Kontakt-Sync",
|
||||
Icon = AppIcon.GetSmallIcon(),
|
||||
ContextMenuStrip = _trayMenu,
|
||||
Visible = true
|
||||
};
|
||||
|
||||
_trayIcon.DoubleClick += (s, e) => ShowMainWindow();
|
||||
|
||||
UpdateTrayMenu();
|
||||
}
|
||||
|
||||
private void UpdateTrayMenu()
|
||||
{
|
||||
_trayMenu.Items.Clear();
|
||||
_trayMenu.Items.Add("Oeffnen", null, (s, e) => ShowMainWindow());
|
||||
_trayMenu.Items.Add("-");
|
||||
|
||||
// Schnell-Sync fuer jedes Profil
|
||||
var profiles = _profileManager.GetProfiles();
|
||||
foreach (var p in profiles.Where(p => p.Enabled))
|
||||
{
|
||||
@@ -142,16 +159,6 @@ namespace StarfaceOutlookSync.UI
|
||||
_trayMenu.Items.Add("-");
|
||||
|
||||
_trayMenu.Items.Add("Beenden", null, (s, e) => ExitApplication());
|
||||
|
||||
_trayIcon = new NotifyIcon
|
||||
{
|
||||
Text = "Starface Kontakt-Sync",
|
||||
Icon = SystemIcons.Application, // Placeholder, wird durch eigenes Icon ersetzt
|
||||
ContextMenuStrip = _trayMenu,
|
||||
Visible = true
|
||||
};
|
||||
|
||||
_trayIcon.DoubleClick += (s, e) => ShowMainWindow();
|
||||
}
|
||||
|
||||
private void SetupAutoSync()
|
||||
@@ -219,7 +226,7 @@ namespace StarfaceOutlookSync.UI
|
||||
}
|
||||
|
||||
// Tray-Menu aktualisieren
|
||||
SetupTrayIcon();
|
||||
UpdateTrayMenu();
|
||||
}
|
||||
|
||||
private void NewProfile()
|
||||
|
||||
@@ -333,9 +333,23 @@ namespace StarfaceOutlookSync.UI
|
||||
};
|
||||
|
||||
if (_isNew)
|
||||
{
|
||||
_pm.AddProfile(profile);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Wenn Adressbuch gewechselt wurde, Mappings zuruecksetzen
|
||||
if (_existingProfile.StarfaceAddressBook?.TagId != profile.StarfaceAddressBook?.TagId
|
||||
|| _existingProfile.StarfaceAddressBook?.Type != profile.StarfaceAddressBook?.Type)
|
||||
{
|
||||
_pm.SaveMappings(profile.Id, new List<SyncMapping>());
|
||||
profile.LastSync = "";
|
||||
MessageBox.Show(
|
||||
"Adressbuch wurde geaendert.\nSync-Zuordnungen wurden automatisch zurueckgesetzt.",
|
||||
"Adressbuch geaendert", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
}
|
||||
_pm.UpdateProfile(profile);
|
||||
}
|
||||
|
||||
DialogResult = DialogResult.OK;
|
||||
Close();
|
||||
|
||||
Reference in New Issue
Block a user