diff --git a/Better-EN5/Better-EN5.csproj b/Better-EN5/Better-EN5.csproj index 03a94a7..bdc09d8 100644 --- a/Better-EN5/Better-EN5.csproj +++ b/Better-EN5/Better-EN5.csproj @@ -7,20 +7,26 @@ enable BetterEN5 Better-EN5 - 1.1.2 - 1.1.0.0 - 1.1.2.0 + 1.2.0 + 1.2.0.0 + 1.2.0.0 雾启工作室 雾启工作室 雾启工作室 - Better-Seewo 增强插件 - 雾生万象,启以为光 — 希沃白板功能增强插件 + Better-Seewo + 雾生万象,启以为光 — Better-Seewo 插件 all + BS-Installer - + + + + + + diff --git a/Better-EN5/InkAutoSaveService.cs b/Better-EN5/InkAutoSaveService.cs new file mode 100644 index 0000000..af6d9e8 --- /dev/null +++ b/Better-EN5/InkAutoSaveService.cs @@ -0,0 +1,85 @@ +using System; +using System.IO; +using System.Text.Json; +using System.Threading.Tasks; +using BetterEN5.Services; + +namespace BetterEN5 +{ + public class InkAutoSaveService + { + private static readonly string SettingsPath = Path.Combine( + Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), + "BetterEN5", "ink-settings.json"); + + public async Task StartAsync() + { + while (true) + { + try + { + var settings = LoadSettings(); + if (settings != null && settings.AutoSaveEnabled) + { + var dir = settings.SaveDirectory; + if (!string.IsNullOrEmpty(dir)) + { + if (!Directory.Exists(dir)) + Directory.CreateDirectory(dir); + var timestamp = DateTime.Now.ToString("yyyyMMdd-HHmmss"); + var filePath = Path.Combine(dir, $"ink-auto-{timestamp}.ink.json"); + var inkService = new InkService(); + await inkService.ExportInkAsync(filePath); + + var retentionMinutes = settings.AutoSaveIntervalMinutes * 2; + CleanOldFiles(dir, TimeSpan.FromMinutes(retentionMinutes > 0 ? retentionMinutes : 10)); + } + } + } + catch { } + + var intervalMinutes = LoadSettings()?.AutoSaveIntervalMinutes ?? 5; + await Task.Delay(TimeSpan.FromMinutes(Math.Max(1, intervalMinutes))); + } + } + + private static InkAutoSaveSettings? LoadSettings() + { + try + { + if (File.Exists(SettingsPath)) + { + var json = File.ReadAllText(SettingsPath); + return JsonSerializer.Deserialize(json); + } + } + catch { } + return null; + } + + private static void CleanOldFiles(string dir, TimeSpan maxAge) + { + try + { + if (!Directory.Exists(dir)) return; + foreach (var file in Directory.GetFiles(dir, "ink-auto-*.ink.json")) + { + try + { + if (DateTime.Now - File.GetCreationTime(file) > maxAge) + File.Delete(file); + } + catch { } + } + } + catch { } + } + } + + public class InkAutoSaveSettings + { + public bool AutoSaveEnabled { get; set; } + public int AutoSaveIntervalMinutes { get; set; } = 5; + public string SaveDirectory { get; set; } = ""; + } +} diff --git a/Better-EN5/Program.cs b/Better-EN5/Program.cs index 38f3963..d99895b 100644 --- a/Better-EN5/Program.cs +++ b/Better-EN5/Program.cs @@ -10,18 +10,16 @@ namespace BetterEN5 { class Program : dotnetCampus.EasiPlugins.EasiPlugin { + private InkAutoSaveService? _autoSaveService; + protected override Task OnRunningAsync() { if (!EN.CommandOptions.IsCloud) { if (EN.App.IsReady) - { Run(); - } else - { EN.App.Ready += App_Ready; - } } return Task.CompletedTask; } @@ -36,6 +34,7 @@ namespace BetterEN5 { await Task.Delay(TimeSpan.FromSeconds(3)); ExportUIItems(); + StartAutoSave(); } private void ExportUIItems() @@ -49,11 +48,18 @@ namespace BetterEN5 new UIItemLangInfo(new CultureInfo("en"), "Export Ink"), }); + manager.AppendWithLang(new BoardMenuImportInk(), + new UIItemAttribute(UIItemPurposes.BoardEditMenu), new[] + { + new UIItemLangInfo(new CultureInfo("zh-CHS"), "导入墨迹"), + new UIItemLangInfo(new CultureInfo("en"), "Import Ink"), + }); + manager.AppendWithLang(new BoardMenuSettings(), new UIItemAttribute(UIItemPurposes.BoardEditMenu), new[] { - new UIItemLangInfo(new CultureInfo("zh-CHS"), "Better-Seewo"), - new UIItemLangInfo(new CultureInfo("en"), "Better-Seewo"), + new UIItemLangInfo(new CultureInfo("zh-CHS"), "Better-Seewo 管理"), + new UIItemLangInfo(new CultureInfo("en"), "Better-Seewo Manager"), }); manager.AppendWithLang(new HeadToolBarSettings(), @@ -63,5 +69,11 @@ namespace BetterEN5 new UIItemLangInfo(new CultureInfo("en"), "Better-Seewo"), }); } + + private void StartAutoSave() + { + _autoSaveService = new InkAutoSaveService(); + _ = _autoSaveService.StartAsync(); + } } } diff --git a/Better-EN5/Services/CustomConversionService.cs b/Better-EN5/Services/CustomConversionService.cs new file mode 100644 index 0000000..8b0c826 --- /dev/null +++ b/Better-EN5/Services/CustomConversionService.cs @@ -0,0 +1,539 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.IO.Compression; +using System.Linq; +using System.Threading.Tasks; +using System.Xml.Linq; + +namespace BetterEN5.Services +{ + public class CustomConversionService : IConversionService + { + private static readonly XNamespace A = "http://schemas.openxmlformats.org/drawingml/2006/main"; + private static readonly XNamespace P = "http://schemas.openxmlformats.org/presentationml/2006/main"; + private static readonly XNamespace R = "http://schemas.openxmlformats.org/officeDocument/2006/relationships"; + private static readonly XNamespace Rel = "http://schemas.openxmlformats.org/package/2006/relationships"; + + public async Task ConvertPptxToEnbxAsync(string pptxPath) + { + if (!File.Exists(pptxPath)) + throw new FileNotFoundException("PPT 文件未找到", pptxPath); + + return await Task.Run(() => + { + var enbxPath = Path.ChangeExtension(pptxPath, ".enbx"); + using var pptx = System.IO.Packaging.Package.Open(pptxPath, FileMode.Open, FileAccess.Read); + using var enbx = System.IO.Packaging.Package.Open(enbxPath, FileMode.Create, FileAccess.ReadWrite); + + var pptxPresentation = GetPptxPresentation(pptx); + var pptxSlideSize = GetSlideSize(pptxPresentation); + var slideWidth = pptxSlideSize.Item1; + var slideHeight = pptxSlideSize.Item2; + + var enbxDoc = new XDocument(); + var board = new XElement("DocumentStorageModel"); + + var slideIds = new List(); + var slidesElement = new XElement("Slides"); + + var slideRels = GetPresentationSlideRels(pptx, pptxPresentation); + for (int i = 0; i < slideRels.Count; i++) + { + var slideId = $"slide_{i + 1}"; + slideIds.Add(slideId); + + var slidePart = pptx.GetPart( + System.IO.Packaging.PackUriHelper.CreatePartUri(new Uri(slideRels[i].Item2, UriKind.Relative))); + var slideXml = XDocument.Load(slidePart.GetStream()); + + var slideElement = new XElement("SlideSaveInfo", + new XElement("Id", slideId), + new XElement("Width", slideWidth), + new XElement("Height", slideHeight)); + + var elementsElement = new XElement("Elements"); + var spTree = slideXml.Root?.Element(P + "cSld")?.Element(P + "spTree"); + if (spTree != null) + { + int elemIdx = 0; + foreach (var sp in spTree.Elements(P + "sp")) + { + var xfrm = sp.Element(P + "spPr")?.Element(A + "xfrm"); + if (xfrm == null) continue; + + var off = xfrm.Element(A + "off"); + var ext = xfrm.Element(A + "ext"); + if (off == null || ext == null) continue; + + var x = (double)off.Attribute("x"); + var y = (double)off.Attribute("y"); + var w = (double)ext.Attribute("cx"); + var h = (double)ext.Attribute("cy"); + + var nvSpPr = sp.Element(P + "nvSpPr"); + var cNvSpPr = nvSpPr?.Element(P + "cNvSpPr"); + var isTextBox = cNvSpPr?.Attribute("txBox") != null; + var txBody = sp.Element(P + "txBody"); + var isTextShape = txBody != null; + + if (isTextBox || isTextShape) + { + var elem = new XElement("TextSaveInfo", + new XElement("Id", $"elem_{++elemIdx}"), + new XElement("X", x), + new XElement("Y", y), + new XElement("Width", w), + new XElement("Height", h), + new XElement("Rotation", 0.0), + new XElement("Locked", false)); + + var bodyPr = txBody?.Element(A + "bodyPr"); + var lIns = (double?)bodyPr?.Attribute("lIns") ?? 91440; + var rIns = (double?)bodyPr?.Attribute("rIns") ?? 91440; + var tIns = (double?)bodyPr?.Attribute("tIns") ?? 91440; + var bIns = (double?)bodyPr?.Attribute("bIns") ?? 91440; + + var richText = new XElement("RichText", + new XElement("LeftMargin", lIns), + new XElement("RightMargin", rIns), + new XElement("TopMargin", tIns), + new XElement("BottomMargin", bIns)); + + if (txBody != null) + { + foreach (var para in txBody.Elements(A + "p")) + { + var pElem = new XElement("Paragraph"); + foreach (var run in para.Elements(A + "r")) + { + var rPr = run.Element(A + "rPr"); + var text = run.Element(A + "t")?.Value ?? ""; + + var rElem = new XElement("Run", + new XElement("Text", text)); + if (rPr != null) + { + var fmt = new XElement("Formatting"); + var sz = rPr.Attribute("sz"); + if (sz != null) fmt.Add(new XElement("Size", (double)sz / 100.0)); + var b = rPr.Attribute("b"); + if (b != null) fmt.Add(new XElement("Bold", (string)b == "1")); + var italicAttr = rPr.Attribute("i"); + if (italicAttr != null) fmt.Add(new XElement("Italic", (string)italicAttr == "1")); + var u = rPr.Attribute("u"); + if (u != null) fmt.Add(new XElement("Underline", u.Value)); + var srgbClr = rPr?.Element(A + "solidFill")?.Element(A + "srgbClr"); + if (srgbClr != null) fmt.Add(new XElement("Color", (string)srgbClr.Attribute("val"))); + var latin = rPr?.Element(A + "latin"); + if (latin != null) fmt.Add(new XElement("Font", (string)latin.Attribute("typeface"))); + if (fmt.HasElements) rElem.Add(fmt); + } + pElem.Add(rElem); + } + richText.Add(pElem); + } + } + + elem.Add(richText); + elementsElement.Add(elem); + } + } + } + + slideElement.Add(elementsElement); + slidesElement.Add(slideElement); + } + + board.Add(new XElement("Board", + new XElement("SlideWidth", slideWidth), + new XElement("SlideHeight", slideHeight), + new XElement("SlideIds", + slideIds.Select(id => new XElement("string", id))))); + board.Add(slidesElement); + enbxDoc.Add(board); + + var enbxPart = enbx.CreatePart( + System.IO.Packaging.PackUriHelper.CreatePartUri(new Uri("/document.xml", UriKind.Relative)), + "application/xml"); + using (var stream = enbxPart.GetStream()) + enbxDoc.Save(stream); + + enbx.Close(); + pptx.Close(); + + return enbxPath; + }); + } + + public async Task ConvertEnbxToPptxAsync(string enbxPath) + { + if (!File.Exists(enbxPath)) + throw new FileNotFoundException("ENBX 文件未找到", enbxPath); + + return await Task.Run(() => + { + var pptxPath = Path.ChangeExtension(enbxPath, ".pptx"); + + using var enbx = System.IO.Packaging.Package.Open(enbxPath, FileMode.Open, FileAccess.Read); + using var pptx = System.IO.Packaging.Package.Open(pptxPath, FileMode.Create, FileAccess.ReadWrite); + + var enbxDocUri = System.IO.Packaging.PackUriHelper.CreatePartUri(new Uri("/document.xml", UriKind.Relative)); + var enbxPart = enbx.GetPart(enbxDocUri); + var enbxDoc = XDocument.Load(enbxPart.GetStream()); + + var root = enbxDoc.Root; + if (root == null) throw new InvalidDataException("无效的 ENBX 文件"); + + var board = root.Element("Board"); + var slideWidth = (double?)board?.Element("SlideWidth") ?? 12192000; + var slideHeight = (double?)board?.Element("SlideHeight") ?? 6858000; + + var slidesEl = root.Element("Slides"); + var slides = slidesEl?.Elements("SlideSaveInfo").ToList() ?? new List(); + + var contentTypesUri = System.IO.Packaging.PackUriHelper.CreatePartUri(new Uri("/[Content_Types].xml", UriKind.Relative)); + var ctPart = pptx.CreatePart(contentTypesUri, "application/xml"); + using (var sw = new StreamWriter(ctPart.GetStream())) + { + sw.Write(""); + sw.Write(""); + sw.Write(""); + sw.Write(""); + sw.Write(""); + sw.Write(""); + sw.Write(""); + sw.Write(""); + for (int i = 0; i < slides.Count; i++) + sw.Write($""); + sw.Write(""); + sw.Write(""); + sw.Write(""); + sw.Write(""); + } + + var pptxPresentation = new XDocument(new XElement(P + "presentation", + new XAttribute(XNamespace.Xmlns + "a", A.NamespaceName), + new XAttribute(XNamespace.Xmlns + "r", R.NamespaceName), + new XAttribute(XNamespace.Xmlns + "p", P.NamespaceName), + new XElement(P + "sldMasterIdLst", + new XElement(P + "sldMasterId", new XAttribute("id", 2147483648), new XAttribute(R + "id", "rId1"))), + new XElement(P + "sldIdLst"), + new XElement(P + "sldSz", new XAttribute("cx", slideWidth), new XAttribute("cy", slideHeight)), + new XElement(P + "notesSz", new XAttribute("cx", 6858000), new XAttribute("cy", 9144000)))); + + var presXmlUri = System.IO.Packaging.PackUriHelper.CreatePartUri(new Uri("/ppt/presentation.xml", UriKind.Relative)); + var presPart = pptx.CreatePart(presXmlUri, "application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml"); + var presRelUri = System.IO.Packaging.PackUriHelper.CreatePartUri(new Uri("/ppt/_rels/presentation.xml.rels", UriKind.Relative)); + var presRelPart = pptx.CreatePart(presRelUri, "application/vnd.openxmlformats-package.relationships+xml"); + + var presRelNs = XNamespace.Get(Rel.NamespaceName); + var presRels = new XDocument(new XElement(presRelNs + "Relationships", + new XElement(presRelNs + "Relationship", new XAttribute("Id", "rId1"), + new XAttribute("Type", "http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideMaster"), + new XAttribute("Target", "slideMasters/slideMaster1.xml")))); + + var slideIdLst = pptxPresentation.Root?.Element(P + "sldIdLst"); + var nextRelId = 2; + var slideRelTargets = new List(); + + for (int i = 0; i < slides.Count; i++) + { + var slideId = $"slide_{i + 1}"; + var slideFileName = $"slides/slide{i + 1}.xml"; + slideRelTargets.Add(slideFileName); + + slideIdLst?.Add(new XElement(P + "sldId", + new XAttribute("id", 256 + i), + new XAttribute(R + "id", $"rId{nextRelId + i}"))); + + presRels.Root?.Add(new XElement("Relationship", + new XAttribute("Id", $"rId{nextRelId + i}"), + new XAttribute("Type", "http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide"), + new XAttribute("Target", slideFileName))); + + var slideDoc = new XDocument(new XElement(P + "sld", + new XAttribute(XNamespace.Xmlns + "a", A.NamespaceName), + new XAttribute(XNamespace.Xmlns + "r", R.NamespaceName), + new XAttribute(XNamespace.Xmlns + "p", P.NamespaceName))); + + var cSld = new XElement(P + "cSld"); + var spTree = new XElement(P + "spTree"); + + spTree.Add(new XElement(P + "nvGrpSpPr", + new XElement(P + "cNvPr", new XAttribute("id", 1), new XAttribute("name", "")), + new XElement(P + "cNvGrpSpPr"))); + spTree.Add(new XElement(P + "grpSpPr", + new XElement(A + "xfrm", + new XElement(A + "off", new XAttribute("x", 0), new XAttribute("y", 0)), + new XElement(A + "ext", new XAttribute("cx", 0), new XAttribute("cy", 0)), + new XElement(A + "chOff", new XAttribute("x", 0), new XAttribute("y", 0)), + new XElement(A + "chExt", new XAttribute("cx", 0), new XAttribute("cy", 0))))); + + var elements = slides[i].Element("Elements"); + if (elements != null) + { + int shapeId = 2; + foreach (var elem in elements.Elements()) + { + var elemName = elem.Name.LocalName; + var x = (double)elem.Element("X"); + var y = (double)elem.Element("Y"); + var w = (double)elem.Element("Width"); + var h = (double)elem.Element("Height"); + var rotation = (double?)elem.Element("Rotation") ?? 0.0; + + if (elemName == "TextSaveInfo") + { + var sp = new XElement(P + "sp"); + sp.Add(new XElement(P + "nvSpPr", + new XElement(P + "cNvPr", new XAttribute("id", shapeId++), new XAttribute("name", $"TextBox{shapeId - 1}")), + new XElement(P + "cNvSpPr", new XAttribute("txBox", 1)), + new XElement(P + "nvPr"))); + + var spPr = new XElement(P + "spPr", + new XElement(A + "xfrm", + new XElement(A + "off", new XAttribute("x", x), new XAttribute("y", y)), + new XElement(A + "ext", new XAttribute("cx", w), new XAttribute("cy", h))), + new XElement(A + "prstGeom", new XAttribute("prst", "rect"), + new XElement(A + "avLst"))); + sp.Add(spPr); + + var txBody = new XElement(P + "txBody", + new XElement(A + "bodyPr", + new XAttribute("wrap", "square"))); + + var richText = elem.Element("RichText"); + if (richText != null) + { + var leftMargin = (double?)richText.Element("LeftMargin") ?? 91440; + var rightMargin = (double?)richText.Element("RightMargin") ?? 91440; + var topMargin = (double?)richText.Element("TopMargin") ?? 91440; + var bottomMargin = (double?)richText.Element("BottomMargin") ?? 91440; + + var bodyPr = txBody.Element(A + "bodyPr"); + if (bodyPr != null) + { + bodyPr.Add(new XAttribute("lIns", leftMargin)); + bodyPr.Add(new XAttribute("rIns", rightMargin)); + bodyPr.Add(new XAttribute("tIns", topMargin)); + bodyPr.Add(new XAttribute("bIns", bottomMargin)); + } + + var paragraphs = richText.Elements("Paragraph"); + if (!paragraphs.Any()) + { + txBody.Add(new XElement(A + "p")); + } + else + { + foreach (var para in paragraphs) + { + var pElem = new XElement(A + "p"); + var runs = para.Elements("Run"); + if (!runs.Any()) + { + pElem.Add(new XElement(A + "endParaRPr")); + } + else + { + foreach (var run in runs) + { + var text = (string)run.Element("Text") ?? ""; + var rElem = new XElement(A + "r"); + var fmt = run.Element("Formatting"); + if (fmt != null) + { + var rPr = new XElement(A + "rPr"); + var sz = fmt.Element("Size"); + if (sz != null) rPr.Add(new XAttribute("sz", (double)sz * 100)); + var bold = fmt.Element("Bold"); + if (bold != null && (bool)bold) rPr.Add(new XAttribute("b", 1)); + var italic = fmt.Element("Italic"); + if (italic != null && (bool)italic) rPr.Add(new XAttribute("i", 1)); + var underline = (string?)fmt.Element("Underline"); + if (underline != null) rPr.Add(new XAttribute("u", underline)); + var color = (string?)fmt.Element("Color"); + if (color != null) + rPr.Add(new XElement(A + "solidFill", new XElement(A + "srgbClr", new XAttribute("val", color)))); + var font = (string?)fmt.Element("Font"); + if (font != null) + rPr.Add(new XElement(A + "latin", new XAttribute("typeface", font))); + if (rPr.HasAttributes || rPr.HasElements) rElem.Add(rPr); + } + rElem.Add(new XElement(A + "t", text)); + pElem.Add(rElem); + } + } + txBody.Add(pElem); + } + } + } + else + { + txBody.Add(new XElement(A + "p")); + } + + sp.Add(txBody); + spTree.Add(sp); + } + } + } + + cSld.Add(spTree); + slideDoc.Root?.Add(cSld); + + var slideUri = System.IO.Packaging.PackUriHelper.CreatePartUri(new Uri($"/ppt/{slideFileName}", UriKind.Relative)); + var slidePart = pptx.CreatePart(slideUri, "application/vnd.openxmlformats-officedocument.presentationml.slide+xml"); + using (var sw = new StreamWriter(slidePart.GetStream())) + slideDoc.Save(sw); + + var slideRelUri = System.IO.Packaging.PackUriHelper.CreatePartUri(new Uri($"/ppt/slides/_rels/slide{i + 1}.xml.rels", UriKind.Relative)); + var slideRelPart = pptx.CreatePart(slideRelUri, "application/vnd.openxmlformats-package.relationships+xml"); + using (var sw = new StreamWriter(slideRelPart.GetStream())) + { + sw.Write(""); + sw.Write(""); + sw.Write(""); + } + } + + var rootRelUri = System.IO.Packaging.PackUriHelper.CreatePartUri(new Uri("/_rels/.rels", UriKind.Relative)); + var rootRelPart = pptx.CreatePart(rootRelUri, "application/vnd.openxmlformats-package.relationships+xml"); + using (var sw = new StreamWriter(rootRelPart.GetStream())) + { + sw.Write(""); + sw.Write(""); + sw.Write(""); + } + + using (var sw = new StreamWriter(presPart.GetStream())) + pptxPresentation.Save(sw); + using (var sw = new StreamWriter(presRelPart.GetStream())) + presRels.Save(sw); + + CreateMinimalTheme(pptx); + CreateMinimalSlideMaster(pptx); + CreateMinimalSlideLayout(pptx); + CreatePresProps(pptx); + CreateViewProps(pptx); + + enbx.Close(); + pptx.Close(); + + return pptxPath; + }); + } + + public Task FixConversionErrorsAsync() + { + var en5Path = Path.Combine( + Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), + "Seewo", "EasiNote5"); + var tempDir = Path.Combine(en5Path, "Temp", "Conversion"); + if (Directory.Exists(tempDir)) + { + try { Directory.Delete(tempDir, true); } catch { } + } + return Task.CompletedTask; + } + + private static Tuple GetSlideSize(XDocument presentation) + { + var sldSz = presentation.Root?.Element(P + "sldSz"); + if (sldSz == null) return Tuple.Create(12192000.0, 6858000.0); + return Tuple.Create( + (double)sldSz.Attribute("cx"), + (double)sldSz.Attribute("cy")); + } + + private static XDocument GetPptxPresentation(System.IO.Packaging.Package pptx) + { + var relsUri = System.IO.Packaging.PackUriHelper.CreatePartUri(new Uri("/_rels/.rels", UriKind.Relative)); + var relsPart = pptx.GetPart(relsUri); + var rels = XDocument.Load(relsPart.GetStream()); + var officeRel = rels.Root?.Elements("Relationship") + .FirstOrDefault(r => (string)r.Attribute("Type") == + "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument"); + if (officeRel == null) throw new InvalidDataException("未找到 Office Document 关系"); + var presUri = System.IO.Packaging.PackUriHelper.CreatePartUri(new Uri((string)officeRel.Attribute("Target"), UriKind.Relative)); + var presPart = pptx.GetPart(presUri); + return XDocument.Load(presPart.GetStream()); + } + + private static List> GetPresentationSlideRels(System.IO.Packaging.Package pptx, XDocument presentation) + { + var relsUri = System.IO.Packaging.PackUriHelper.CreatePartUri(new Uri("/ppt/_rels/presentation.xml.rels", UriKind.Relative)); + var relsPart = pptx.GetPart(relsUri); + var rels = XDocument.Load(relsPart.GetStream()); + var slideType = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide"; + return rels.Root?.Elements("Relationship") + .Where(r => (string)r.Attribute("Type") == slideType) + .Select(r => Tuple.Create((string)r.Attribute("Id"), (string)r.Attribute("Target"))) + .ToList() ?? new List>(); + } + + private static void CreateMinimalTheme(System.IO.Packaging.Package pptx) + { + var themeUri = System.IO.Packaging.PackUriHelper.CreatePartUri(new Uri("/ppt/theme/theme1.xml", UriKind.Relative)); + var themePart = pptx.CreatePart(themeUri, "application/vnd.openxmlformats-officedocument.theme+xml"); + using (var sw = new StreamWriter(themePart.GetStream())) + { + sw.Write(""); + sw.Write(""); + sw.Write(""); + sw.Write(""); + sw.Write(""); + sw.Write(""); + } + } + + private static void CreateMinimalSlideMaster(System.IO.Packaging.Package pptx) + { + var masterUri = System.IO.Packaging.PackUriHelper.CreatePartUri(new Uri("/ppt/slideMasters/slideMaster1.xml", UriKind.Relative)); + var masterPart = pptx.CreatePart(masterUri, "application/vnd.openxmlformats-officedocument.presentationml.slideMaster+xml"); + using (var sw = new StreamWriter(masterPart.GetStream())) + { + sw.Write(""); + sw.Write(""); + sw.Write(""); + } + + var masterRelUri = System.IO.Packaging.PackUriHelper.CreatePartUri(new Uri("/ppt/slideMasters/_rels/slideMaster1.xml.rels", UriKind.Relative)); + var masterRelPart = pptx.CreatePart(masterRelUri, "application/vnd.openxmlformats-package.relationships+xml"); + using (var sw = new StreamWriter(masterRelPart.GetStream())) + { + sw.Write(""); + sw.Write(""); + sw.Write(""); + } + } + + private static void CreateMinimalSlideLayout(System.IO.Packaging.Package pptx) + { + var layoutUri = System.IO.Packaging.PackUriHelper.CreatePartUri(new Uri("/ppt/slideLayouts/slideLayout1.xml", UriKind.Relative)); + var layoutPart = pptx.CreatePart(layoutUri, "application/vnd.openxmlformats-officedocument.presentationml.slideLayout+xml"); + using (var sw = new StreamWriter(layoutPart.GetStream())) + { + sw.Write(""); + sw.Write(""); + } + } + + private static void CreatePresProps(System.IO.Packaging.Package pptx) + { + var uri = System.IO.Packaging.PackUriHelper.CreatePartUri(new Uri("/ppt/presProps.xml", UriKind.Relative)); + var part = pptx.CreatePart(uri, "application/vnd.openxmlformats-officedocument.presentationml.presProps+xml"); + using (var sw = new StreamWriter(part.GetStream())) + sw.Write(""); + } + + private static void CreateViewProps(System.IO.Packaging.Package pptx) + { + var uri = System.IO.Packaging.PackUriHelper.CreatePartUri(new Uri("/ppt/viewProps.xml", UriKind.Relative)); + var part = pptx.CreatePart(uri, "application/vnd.openxmlformats-officedocument.presentationml.viewProps+xml"); + using (var sw = new StreamWriter(part.GetStream())) + sw.Write(""); + } + } +} diff --git a/Better-EN5/Services/PatchService.cs b/Better-EN5/Services/PatchService.cs index e95228d..2fda154 100644 --- a/Better-EN5/Services/PatchService.cs +++ b/Better-EN5/Services/PatchService.cs @@ -46,7 +46,7 @@ namespace BetterEN5.Services var manifest = new PatchManifest { InstallTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), - Version = "1.1.2" + Version = "1.2.0" }; BackupFile(manifest, diff --git a/Better-EN5/UI/BetterSeewoMainWindow.xaml b/Better-EN5/UI/BetterSeewoMainWindow.xaml deleted file mode 100644 index 02544ba..0000000 --- a/Better-EN5/UI/BetterSeewoMainWindow.xaml +++ /dev/null @@ -1,188 +0,0 @@ - - - #0F0F1A - #1A1A2E - #60B0FF - #D0D0E0 - #707090 - - - - - - - - - - - - - - - - - - - - - - - - - - -