mirror of
https://github.com/CloverHackyColor/CloverBootloader.git
synced 2025-01-10 19:18:25 +01:00
Clover.app: added LAbyOne's theme repository + themeout of date theme detection
HelmoHass themes repository (by LAbyOne) can be selected directly in the UI. Now the theme manager knows when a theme is out dated and show a dedicate icon when this happens. Now Clover.app can encode the git sha1 ... always with out git. Searching themes in the relative fields is now even more easy by tipying the name partially in case insensitive mode. builme now close the Terminal window when exit is selected (thanks to LAbyOne). Fixed a bug in the theme manager engine switching between repositories.
This commit is contained in:
parent
ea3058f867
commit
a4c90606d1
@ -22,6 +22,7 @@
|
||||
9542ABC02373783400DC03E6 /* boot1-install in Copy tools */ = {isa = PBXBuildFile; fileRef = 9542ABBD2373780C00DC03E6 /* boot1-install */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
|
||||
9542ABC22373786700DC03E6 /* CloverV2 in Copy CloverV2 */ = {isa = PBXBuildFile; fileRef = 9542ABC12373786700DC03E6 /* CloverV2 */; };
|
||||
9546AE1B23806299007155A6 /* CloverLogOut in Copy tools */ = {isa = PBXBuildFile; fileRef = 95524B88238051F4005F6425 /* CloverLogOut */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
|
||||
954B0385243EB0AB001E719A /* update.png in Resources */ = {isa = PBXBuildFile; fileRef = 954B0384243EB0AB001E719A /* update.png */; };
|
||||
954BBE99238196EE0032425F /* Locale.swift in Sources */ = {isa = PBXBuildFile; fileRef = 954BBE98238196EE0032425F /* Locale.swift */; };
|
||||
954DECD523899F5F006A9876 /* Bootmanager.png in Resources */ = {isa = PBXBuildFile; fileRef = 954DECD423899F5F006A9876 /* Bootmanager.png */; };
|
||||
954FCFD92391818300C9273C /* NSWindowFix.m in Sources */ = {isa = PBXBuildFile; fileRef = 954FCFD82391818300C9273C /* NSWindowFix.m */; };
|
||||
@ -240,6 +241,7 @@
|
||||
953BC20223720C0A0039755D /* FixedWidthViews.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FixedWidthViews.swift; sourceTree = "<group>"; };
|
||||
9542ABB82373780C00DC03E6 /* boot1-inst.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "boot1-inst.xcodeproj"; path = "../CloverPackage/utils/boot1-install/boot1-inst.xcodeproj"; sourceTree = "<group>"; };
|
||||
9542ABC12373786700DC03E6 /* CloverV2 */ = {isa = PBXFileReference; lastKnownFileType = folder; name = CloverV2; path = ../CloverPackage/CloverV2; sourceTree = "<group>"; };
|
||||
954B0384243EB0AB001E719A /* update.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = update.png; sourceTree = "<group>"; };
|
||||
954BBE98238196EE0032425F /* Locale.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Locale.swift; sourceTree = "<group>"; };
|
||||
954C3DF0237DF0250059C698 /* ServiceManagement.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ServiceManagement.framework; path = System/Library/Frameworks/ServiceManagement.framework; sourceTree = SDKROOT; };
|
||||
954DECD423899F5F006A9876 /* Bootmanager.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Bootmanager.png; sourceTree = "<group>"; };
|
||||
@ -570,6 +572,7 @@
|
||||
9534B79A242CDC52003F323E /* Find.png */,
|
||||
9534B799242CDC52003F323E /* Replace.png */,
|
||||
955BEE1A23C7171000425AB0 /* check.png */,
|
||||
954B0384243EB0AB001E719A /* update.png */,
|
||||
);
|
||||
path = images;
|
||||
sourceTree = "<group>";
|
||||
@ -861,6 +864,7 @@
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
954B0385243EB0AB001E719A /* update.png in Resources */,
|
||||
9534B79B242CDC53003F323E /* Replace.png in Resources */,
|
||||
9571A22A241C2E7F000D6645 /* PlistEditor.storyboard in Resources */,
|
||||
9556CAF5238DF75600082671 /* InstallerOutline.xib in Resources */,
|
||||
|
@ -80,7 +80,7 @@
|
||||
<rect key="frame" x="14" y="186" width="311" height="14"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" controlSize="small" lineBreakMode="clipping" title="Check update:" id="fMZ-r2-dlm">
|
||||
<font key="font" metaFont="label" size="11"/>
|
||||
<font key="font" metaFont="menu" size="11"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
@ -89,7 +89,7 @@
|
||||
<rect key="frame" x="14" y="91" width="311" height="14"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" controlSize="small" lineBreakMode="clipping" title="Label" id="v3d-HG-AeW">
|
||||
<font key="font" metaFont="label" size="11"/>
|
||||
<font key="font" metaFont="menu" size="11"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
@ -195,7 +195,7 @@
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="push" title="Read daemon log" bezelStyle="rounded" alignment="center" controlSize="small" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="UZY-ie-enb">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="label" size="11"/>
|
||||
<font key="font" metaFont="menu" size="11"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="readDaemonLog:" target="tSJ-3G-dnL" id="Mo0-RL-dK0"/>
|
||||
@ -206,7 +206,7 @@
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="push" title="Read bdmesg" bezelStyle="rounded" alignment="center" controlSize="small" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="bhg-iF-USh">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="label" size="11"/>
|
||||
<font key="font" metaFont="menu" size="11"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="readbdmesg:" target="tSJ-3G-dnL" id="eFP-wf-VyP"/>
|
||||
@ -216,7 +216,7 @@
|
||||
<rect key="frame" x="61" y="9" width="224" height="15"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" controlSize="small" lineBreakMode="clipping" alignment="center" title="Label" id="goU-fD-Ng6">
|
||||
<font key="font" metaFont="label" size="11"/>
|
||||
<font key="font" metaFont="menu" size="11"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
@ -284,7 +284,7 @@
|
||||
<rect key="frame" x="30" y="20" width="294" height="14"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" controlSize="small" lineBreakMode="truncatingHead" selectable="YES" allowsUndo="NO" focusRingType="none" title="N/A" id="EX6-6q-G8U">
|
||||
<font key="font" metaFont="label" size="11"/>
|
||||
<font key="font" metaFont="menu" size="11"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
@ -298,7 +298,7 @@
|
||||
<rect key="frame" x="30" y="56" width="294" height="14"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<textFieldCell key="cell" controlSize="small" lineBreakMode="clipping" selectable="YES" allowsUndo="NO" title="N/A" id="EFW-lW-i6c">
|
||||
<font key="font" metaFont="label" size="11"/>
|
||||
<font key="font" metaFont="menu" size="11"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
@ -324,7 +324,7 @@
|
||||
<rect key="frame" x="30" y="79" width="294" height="14"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<textFieldCell key="cell" controlSize="small" lineBreakMode="clipping" selectable="YES" focusRingType="none" title="N/A" id="PZZ-nm-ERe">
|
||||
<font key="font" metaFont="label" size="11"/>
|
||||
<font key="font" metaFont="menu" size="11"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
@ -342,7 +342,7 @@
|
||||
<rect key="frame" x="30" y="39" width="294" height="14"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<textFieldCell key="cell" controlSize="small" lineBreakMode="clipping" selectable="YES" focusRingType="none" title="N/A" id="oPZ-3Y-89o">
|
||||
<font key="font" metaFont="label" size="11"/>
|
||||
<font key="font" metaFont="menu" size="11"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
@ -360,7 +360,7 @@
|
||||
<rect key="frame" x="30" y="0.0" width="294" height="14"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<textFieldCell key="cell" controlSize="small" lineBreakMode="clipping" selectable="YES" focusRingType="none" title="N/A" id="okN-IH-2al">
|
||||
<font key="font" metaFont="label" size="11"/>
|
||||
<font key="font" metaFont="menu" size="11"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
@ -386,7 +386,7 @@
|
||||
<rect key="frame" x="30" y="79" width="294" height="14"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<textFieldCell key="cell" controlSize="small" lineBreakMode="clipping" selectable="YES" focusRingType="none" title="N/A" id="HZg-rD-gZv">
|
||||
<font key="font" metaFont="label" size="11"/>
|
||||
<font key="font" metaFont="menu" size="11"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
@ -413,7 +413,7 @@
|
||||
<rect key="frame" x="30" y="39" width="294" height="14"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<textFieldCell key="cell" controlSize="small" lineBreakMode="clipping" selectable="YES" focusRingType="none" title="Label" id="J7N-7a-sdN">
|
||||
<font key="font" metaFont="label" size="11"/>
|
||||
<font key="font" metaFont="menu" size="11"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
@ -422,7 +422,7 @@
|
||||
<rect key="frame" x="30" y="0.0" width="294" height="14"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<textFieldCell key="cell" controlSize="small" lineBreakMode="clipping" selectable="YES" focusRingType="none" title="Label" id="0dT-GZ-Ytt">
|
||||
<font key="font" metaFont="label" size="11"/>
|
||||
<font key="font" metaFont="menu" size="11"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
@ -474,7 +474,7 @@
|
||||
<rect key="frame" x="256" y="497" width="69" height="21"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<segmentedCell key="cell" controlSize="small" borderStyle="border" alignment="left" style="rounded" trackingMode="momentary" id="3O5-bI-89P">
|
||||
<font key="font" metaFont="label" size="11"/>
|
||||
<font key="font" metaFont="menu" size="11"/>
|
||||
<segments>
|
||||
<segment image="NSLeftFacingTriangleTemplate" width="31"/>
|
||||
<segment image="NSRightFacingTriangleTemplate" width="31" tag="1"/>
|
||||
@ -490,7 +490,7 @@
|
||||
<font key="font" metaFont="system"/>
|
||||
<tabViewItems>
|
||||
<tabViewItem identifier="Mount" id="F4n-I1-4Gq">
|
||||
<view key="view" id="E05-QZ-1bf">
|
||||
<view key="view" ambiguous="YES" id="E05-QZ-1bf">
|
||||
<rect key="frame" x="0.0" y="0.0" width="342" height="113"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
@ -569,24 +569,66 @@
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<comboBox verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="MMH-mb-fPM">
|
||||
<rect key="frame" x="23" y="65" width="302" height="25"/>
|
||||
<rect key="frame" x="23" y="67" width="302" height="25"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<comboBoxCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" borderStyle="bezel" placeholderString="NVRAM" drawsBackground="YES" completes="NO" numberOfVisibleItems="5" id="kdy-IM-YSv">
|
||||
<comboBoxCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" borderStyle="bezel" placeholderString="NVRAM" drawsBackground="YES" completes="NO" usesDataSource="YES" numberOfVisibleItems="5" id="kdy-IM-YSv">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
<objectValues>
|
||||
<string>Item 1</string>
|
||||
<string>Item 2</string>
|
||||
<string>Item 3</string>
|
||||
</objectValues>
|
||||
</comboBoxCell>
|
||||
<connections>
|
||||
<outlet property="dataSource" destination="tSJ-3G-dnL" id="edh-mp-ILZ"/>
|
||||
<outlet property="delegate" destination="tSJ-3G-dnL" id="kY4-3y-8Vx"/>
|
||||
</connections>
|
||||
</comboBox>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="6VD-VJ-phW">
|
||||
<rect key="frame" x="21" y="48" width="75" height="14"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<textFieldCell key="cell" controlSize="small" lineBreakMode="clipping" title="GitHub user" id="Bi4-5Q-YMR">
|
||||
<font key="font" metaFont="menu" size="11"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="QbU-PE-PmE">
|
||||
<rect key="frame" x="21" y="28" width="75" height="14"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<textFieldCell key="cell" controlSize="small" lineBreakMode="clipping" title="GitHub repo" id="dE6-xG-swG">
|
||||
<font key="font" metaFont="menu" size="11"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="2Va-F7-vYB">
|
||||
<rect key="frame" x="102" y="26" width="220" height="18"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<textFieldCell key="cell" controlSize="small" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" drawsBackground="YES" id="dmw-9Z-gN5">
|
||||
<font key="font" metaFont="menu" size="11"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<connections>
|
||||
<outlet property="delegate" destination="tSJ-3G-dnL" id="tWZ-Mw-jdD"/>
|
||||
</connections>
|
||||
</textField>
|
||||
<comboBox verticalHuggingPriority="750" fixedFrame="YES" textCompletion="NO" translatesAutoresizingMaskIntoConstraints="NO" id="81R-f3-rAr">
|
||||
<rect key="frame" x="102" y="43" width="223" height="22"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<comboBoxCell key="cell" controlSize="small" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" drawsBackground="YES" numberOfVisibleItems="2" id="JjI-1A-wBD">
|
||||
<font key="font" metaFont="menu" size="11"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<objectValues>
|
||||
<string>CloverHackyColor</string>
|
||||
<string>HelmoHass</string>
|
||||
</objectValues>
|
||||
</comboBoxCell>
|
||||
<connections>
|
||||
<outlet property="delegate" destination="tSJ-3G-dnL" id="dOk-qJ-DYi"/>
|
||||
</connections>
|
||||
</comboBox>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="AzG-cL-pFW">
|
||||
<rect key="frame" x="17" y="33" width="311" height="32"/>
|
||||
<rect key="frame" x="17" y="-7" width="311" height="32"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="push" title="Manager" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="I4v-1L-brN">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
@ -596,48 +638,6 @@
|
||||
<action selector="openThemeManager:" target="tSJ-3G-dnL" id="PE4-2e-cP2"/>
|
||||
</connections>
|
||||
</button>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="6VD-VJ-phW">
|
||||
<rect key="frame" x="21" y="20" width="75" height="14"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<textFieldCell key="cell" controlSize="small" lineBreakMode="clipping" title="GitHub user" id="Bi4-5Q-YMR">
|
||||
<font key="font" metaFont="label" size="11"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="QbU-PE-PmE">
|
||||
<rect key="frame" x="21" y="2" width="75" height="14"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<textFieldCell key="cell" controlSize="small" lineBreakMode="clipping" title="GitHub repo" id="dE6-xG-swG">
|
||||
<font key="font" metaFont="label" size="11"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="2Va-F7-vYB">
|
||||
<rect key="frame" x="102" y="1" width="220" height="16"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<textFieldCell key="cell" controlSize="mini" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" id="dmw-9Z-gN5">
|
||||
<font key="font" metaFont="label" size="9"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<connections>
|
||||
<outlet property="delegate" destination="tSJ-3G-dnL" id="tWZ-Mw-jdD"/>
|
||||
</connections>
|
||||
</textField>
|
||||
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="rfY-Ds-j3c">
|
||||
<rect key="frame" x="102" y="19" width="220" height="16"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<textFieldCell key="cell" controlSize="mini" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" id="glm-s6-df6">
|
||||
<font key="font" metaFont="label" size="9"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<connections>
|
||||
<outlet property="delegate" destination="tSJ-3G-dnL" id="IJL-eP-tCC"/>
|
||||
</connections>
|
||||
</textField>
|
||||
</subviews>
|
||||
</view>
|
||||
</tabViewItem>
|
||||
@ -676,7 +676,7 @@
|
||||
<rect key="frame" x="18" y="94" width="306" height="14"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<textFieldCell key="cell" controlSize="small" lineBreakMode="clipping" alignment="right" title="Startup Sound" id="Vif-FP-OaO">
|
||||
<font key="font" metaFont="label" size="11"/>
|
||||
<font key="font" metaFont="menu" size="11"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
@ -699,7 +699,7 @@
|
||||
<rect key="frame" x="18" y="25" width="306" height="14"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<textFieldCell key="cell" controlSize="small" lineBreakMode="clipping" title="Volume level:" id="ebr-lB-pTD">
|
||||
<font key="font" metaFont="label" size="11"/>
|
||||
<font key="font" metaFont="menu" size="11"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
@ -708,7 +708,7 @@
|
||||
<rect key="frame" x="18" y="79" width="241" height="14"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<textFieldCell key="cell" controlSize="small" lineBreakMode="clipping" title="Device:" id="sIi-by-bNC">
|
||||
<font key="font" metaFont="label" size="11"/>
|
||||
<font key="font" metaFont="menu" size="11"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
@ -727,7 +727,7 @@
|
||||
</tabViewItem>
|
||||
<tabViewItem identifier="clover-genconfig" id="kc7-iD-ZPw">
|
||||
<nil key="label"/>
|
||||
<view key="view" ambiguous="YES" id="Lp8-6t-ak1">
|
||||
<view key="view" id="Lp8-6t-ak1">
|
||||
<rect key="frame" x="0.0" y="0.0" width="342" height="113"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
@ -898,7 +898,7 @@
|
||||
<outlet property="tabViewInfo" destination="PGs-4a-XRc" id="ghG-r0-tYY"/>
|
||||
<outlet property="themeBox" destination="MMH-mb-fPM" id="2nx-c0-WqX"/>
|
||||
<outlet property="themeRepoField" destination="2Va-F7-vYB" id="o15-c9-jRd"/>
|
||||
<outlet property="themeUserField" destination="rfY-Ds-j3c" id="RNj-Rn-fsb"/>
|
||||
<outlet property="themeUserCBox" destination="81R-f3-rAr" id="i8d-tx-SIs"/>
|
||||
<outlet property="timeIntervalPopUp" destination="1qf-uO-CvA" id="774-SY-GdB"/>
|
||||
<outlet property="unInstallDaemonButton" destination="MWn-i4-CYn" id="r2Y-WW-wd9"/>
|
||||
<outlet property="unmountButton" destination="Zc5-Dl-jIh" id="5wb-ye-REX"/>
|
||||
|
@ -7,6 +7,7 @@
|
||||
//
|
||||
|
||||
import Cocoa
|
||||
import CommonCrypto
|
||||
|
||||
extension String {
|
||||
/// Create `Data` from hexadecimal string representation
|
||||
@ -253,6 +254,15 @@ extension Data {
|
||||
.joined(separator: "")
|
||||
}
|
||||
|
||||
var sha1: String {
|
||||
var h = [UInt8](repeating: 0, count: Int(CC_SHA1_DIGEST_LENGTH))
|
||||
|
||||
self.withUnsafeBytes {
|
||||
_ = CC_SHA1($0.baseAddress, CC_LONG(self.count), &h)
|
||||
}
|
||||
return Data(h).hexadecimal()
|
||||
}
|
||||
|
||||
func castToCPointer<T>() -> T {
|
||||
let mem = UnsafeMutablePointer<T>.allocate(capacity: 1)
|
||||
_ = self.copyBytes(to: UnsafeMutableBufferPointer(start: mem, count: 1))
|
||||
|
@ -37,7 +37,7 @@ final class SoundSlider : NSSlider {
|
||||
}
|
||||
|
||||
final class SettingsViewController:
|
||||
NSViewController, NSTextFieldDelegate, NSComboBoxDelegate, URLSessionDownloadDelegate {
|
||||
NSViewController, NSTextFieldDelegate, NSComboBoxDelegate, NSComboBoxDataSource, URLSessionDownloadDelegate {
|
||||
// MARK: Variables
|
||||
@IBOutlet var tabViewInfo : LITabView!
|
||||
// tab 0
|
||||
@ -66,7 +66,7 @@ final class SettingsViewController:
|
||||
// tab 1
|
||||
@IBOutlet var themeBox : NSComboBox!
|
||||
@IBOutlet var openThemeButton : NSButton!
|
||||
@IBOutlet var themeUserField : NSTextField!
|
||||
@IBOutlet var themeUserCBox : NSComboBox!
|
||||
@IBOutlet var themeRepoField : NSTextField!
|
||||
// tab 2
|
||||
@IBOutlet var soundDevicePopUp : NSPopUpButton!
|
||||
@ -145,15 +145,18 @@ final class SettingsViewController:
|
||||
AppSD.themeUser = UDs.string(forKey: kThemeUserKey) ?? kDefaultThemeUser
|
||||
AppSD.themeRepo = UDs.string(forKey: kThemeRepoKey) ?? kDefaultThemeRepo
|
||||
|
||||
self.themeUserField.stringValue = AppSD.themeUser
|
||||
self.themeUserCBox.stringValue = AppSD.themeUser
|
||||
self.themeRepoField.stringValue = AppSD.themeRepo
|
||||
|
||||
if #available(OSX 10.10, *) {
|
||||
self.themeUserField.placeholderString = kDefaultThemeUser
|
||||
self.themeUserCBox.placeholderString = kDefaultThemeUser
|
||||
self.themeRepoField.placeholderString = kDefaultThemeRepo
|
||||
}
|
||||
|
||||
self.themeBox.removeAllItems()
|
||||
self.themeUserCBox.removeAllItems()
|
||||
self.themeUserCBox.completes = true
|
||||
self.themeUserCBox.addItems(withObjectValues: ["CloverHackyColor", "HelmoHass"])
|
||||
|
||||
let themeManagerIndexDir = NSHomeDirectory().addPath("Library/Application Support/CloverApp/Themeindex/\(AppSD.themeUser)_\(AppSD.themeRepo)")
|
||||
|
||||
let tm = ThemeManager(user: AppSD.themeUser,
|
||||
@ -162,18 +165,22 @@ final class SettingsViewController:
|
||||
indexDir: themeManagerIndexDir,
|
||||
delegate: nil)
|
||||
|
||||
let indexedThemes = tm.getIndexedThemes()
|
||||
self.themeBox.addItems(withObjectValues: indexedThemes)
|
||||
let indexedThemes = tm.getIndexedThemesForAllRepositories()
|
||||
AppSD.themes = indexedThemes.sorted()
|
||||
|
||||
if indexedThemes.contains("embedded") {
|
||||
self.themeBox.addItem(withObjectValue: "embedded")
|
||||
if !AppSD.themes.contains("embedded") {
|
||||
AppSD.themes.append("embedded")
|
||||
}
|
||||
|
||||
if indexedThemes.contains("random") {
|
||||
self.themeBox.addItem(withObjectValue: "random")
|
||||
if !AppSD.themes.contains("random") {
|
||||
AppSD.themes.append("random")
|
||||
}
|
||||
|
||||
|
||||
self.themeBox.delegate = self
|
||||
self.themeBox.dataSource = self
|
||||
self.themeBox.usesDataSource = true
|
||||
self.themeBox.completes = true
|
||||
self.themeBox.reloadData()
|
||||
|
||||
self.soundVolumeSlider.field = self.soundVolumeField
|
||||
self.soundVolumeField.stringValue = kNotAvailable.locale
|
||||
@ -636,41 +643,65 @@ final class SettingsViewController:
|
||||
}
|
||||
}
|
||||
|
||||
func numberOfItems(in comboBox: NSComboBox) -> Int {
|
||||
return AppSD.themes.count
|
||||
}
|
||||
|
||||
func comboBox(_ comboBox: NSComboBox, indexOfItemWithStringValue string: String) -> Int {
|
||||
return AppSD.themes.firstIndex(of: string) ?? -1
|
||||
}
|
||||
func comboBox(_ comboBox: NSComboBox, objectValueForItemAt index: Int) -> Any? {
|
||||
return AppSD.themes[index]
|
||||
}
|
||||
|
||||
func comboBox(_ comboBox: NSComboBox, completedString string: String) -> String? {
|
||||
for theme in AppSD.themes {
|
||||
if theme.lowercased().hasPrefix(string.lowercased()) {
|
||||
return theme
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func comboBoxSelectionDidChange(_ notification: Notification) {
|
||||
if (notification.object as? NSComboBox) == self.themeBox {
|
||||
self.themeBoxSelected(self.themeBox)
|
||||
let themeName = self.themeBox.itemObjectValue(at: self.themeBox.indexOfSelectedItem) as! String
|
||||
self.set(theme: themeName, sender: self.themeBox)
|
||||
} else if (notification.object as? NSComboBox) == self.themeUserCBox {
|
||||
let val = self.themeUserCBox.itemObjectValue(at: self.themeUserCBox.indexOfSelectedItem) as! String
|
||||
UDs.set(val, forKey: kThemeUserKey)
|
||||
UDs.synchronize()
|
||||
AppSD.themeUser = val
|
||||
}
|
||||
}
|
||||
|
||||
func controlTextDidEndEditing(_ obj: Notification) {
|
||||
if (obj.object as? NSComboBox) == self.themeBox {
|
||||
self.themeBoxSelected(self.themeBox)
|
||||
let themeName = self.themeBox.stringValue
|
||||
self.set(theme: themeName, sender: self.themeBox)
|
||||
return
|
||||
}
|
||||
var updateThemeRepo = false
|
||||
if let field = obj.object as? NSTextField {
|
||||
|
||||
if field == self.themeUserField {
|
||||
if field.stringValue.count > 0 {
|
||||
UDs.set(field.stringValue, forKey: kThemeUserKey)
|
||||
|
||||
if let cbox = obj.object as? NSComboBox {
|
||||
if cbox == self.themeUserCBox {
|
||||
if cbox.stringValue.count > 0 {
|
||||
UDs.set(cbox.stringValue, forKey: kThemeUserKey)
|
||||
} else {
|
||||
UDs.set(kDefaultThemeUser, forKey: kThemeUserKey)
|
||||
}
|
||||
updateThemeRepo = true
|
||||
} else if field == self.themeRepoField {
|
||||
AppSD.themeUser = UDs.string(forKey: kThemeUserKey) ?? kDefaultThemeUser
|
||||
}
|
||||
} else if let field = obj.object as? NSTextField {
|
||||
if field == self.themeRepoField {
|
||||
if field.stringValue.count > 0 {
|
||||
UDs.set(field.stringValue, forKey: kThemeRepoKey)
|
||||
} else {
|
||||
UDs.set(kDefaultThemeRepo, forKey: kThemeRepoKey)
|
||||
}
|
||||
updateThemeRepo = true
|
||||
UDs.synchronize()
|
||||
AppSD.themeRepo = UDs.string(forKey: kThemeRepoKey) ?? kDefaultThemeRepo
|
||||
}
|
||||
}
|
||||
|
||||
if updateThemeRepo {
|
||||
AppSD.themeUser = UDs.string(forKey: kThemeUserKey) ?? kDefaultThemeUser
|
||||
AppSD.themeRepo = UDs.string(forKey: kThemeRepoKey) ?? kDefaultThemeRepo
|
||||
}
|
||||
}
|
||||
|
||||
@IBAction func generateConfig(_ sender: NSButton!) {
|
||||
@ -933,19 +964,22 @@ final class SettingsViewController:
|
||||
|
||||
// MARK: NVRAM editing
|
||||
func themeBoxSelected(_ sender: NSComboBox!) {
|
||||
//sender.window?.makeFirstResponder(nil)
|
||||
let themeName = sender.itemObjectValue(at: sender.indexOfSelectedItem) as! String
|
||||
self.set(theme: themeName, sender: sender)
|
||||
}
|
||||
|
||||
private func set(theme name: String, sender: NSComboBox) {
|
||||
let key = "Clover.Theme"
|
||||
let theme = sender.stringValue
|
||||
var nvramValue : String = ""
|
||||
if let data = getNVRAM()?.object(forKey: key) as? Data {
|
||||
nvramValue = String(decoding: data, as: UTF8.self)
|
||||
}
|
||||
|
||||
if nvramValue != theme {
|
||||
if theme.count == 0 {
|
||||
if nvramValue != name {
|
||||
if name.count == 0 {
|
||||
deleteNVRAM(key: key.nvramString)
|
||||
} else {
|
||||
setNVRAM(key: key, stringValue: theme.nvramString)
|
||||
setNVRAM(key: key, stringValue: name.nvramString)
|
||||
}
|
||||
} else {
|
||||
return
|
||||
|
@ -7,6 +7,7 @@
|
||||
//
|
||||
|
||||
import Cocoa
|
||||
import CommonCrypto
|
||||
|
||||
let kThemeUserKey = "themeUser"
|
||||
let kThemeRepoKey = "themeRepo"
|
||||
@ -31,11 +32,11 @@ final class ThemeManager: NSObject, URLSessionDataDelegate {
|
||||
private let errorDomain : String = "org.slice.Clover.ThemeManager.Error"
|
||||
var statusError : Error? = nil
|
||||
var delegate : ThemeManagerVC?
|
||||
private var user : String
|
||||
private var repo : String
|
||||
var user : String
|
||||
var repo : String
|
||||
var basePath : String
|
||||
private var urlBaseStr : String
|
||||
private var themeManagerIndexDir : String
|
||||
var themeManagerIndexDir : String
|
||||
|
||||
private var gitInitCount : Int32 = 0
|
||||
|
||||
@ -58,6 +59,31 @@ final class ThemeManager: NSObject, URLSessionDataDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
public func getIndexedThemesForAllRepositories() -> [String] {
|
||||
self.statusError = nil
|
||||
var themes = [String]()
|
||||
let tip = NSHomeDirectory().addPath("Library/Application Support/CloverApp/Themeindex")
|
||||
|
||||
if let repos = try? fm.contentsOfDirectory(atPath: tip) {
|
||||
for repo in repos {
|
||||
let repoThemesDir = tip.addPath(repo).addPath("Themes")
|
||||
let repoShaFilePath = tip.addPath(repo).addPath("sha")
|
||||
if fm.fileExists(atPath: repoShaFilePath) && fm.fileExists(atPath: repoThemesDir) {
|
||||
if let files : [String] = try? fm.contentsOfDirectory(atPath: repoThemesDir) {
|
||||
for f in files {
|
||||
let theme : String = f.deletingFileExtension
|
||||
let ext : String = f.fileExtension
|
||||
if ext == "plist" && !themes.contains(theme) {
|
||||
themes.append(theme)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return themes.sorted()
|
||||
}
|
||||
|
||||
public func getIndexedThemes() -> [String] {
|
||||
self.statusError = nil
|
||||
var themes = [String]()
|
||||
@ -367,18 +393,34 @@ final class ThemeManager: NSObject, URLSessionDataDelegate {
|
||||
completion(false)
|
||||
break
|
||||
}
|
||||
|
||||
|
||||
if let path = obj["path"] as? String {
|
||||
if path.componentsPath.count == 1 && type != "tree" {
|
||||
// skip every things is not a directory in the root of the repository (like README.md)
|
||||
continue
|
||||
}
|
||||
|
||||
if !path.hasPrefix(".") && type == "blob" { // .gitignore, .DS_Store
|
||||
guard let fileSha = obj["sha"] as? String else {
|
||||
let errStr = "GI16, Error: 'sha' key not found for \(path)."
|
||||
let se : Error = NSError(domain: self.errorDomain,
|
||||
code: 2016,
|
||||
userInfo: [NSLocalizedDescriptionKey: errStr])
|
||||
|
||||
self.statusError = se
|
||||
completion(false)
|
||||
break
|
||||
}
|
||||
|
||||
// skip every hidden files like .gitignore, .DS_Store, etc.
|
||||
if !path.hasPrefix(".") && type == "blob" {
|
||||
let themeName : String = path.components(separatedBy: "/")[0]
|
||||
let plistPath : String = "\(self.themeManagerIndexDir)/\(sha)/\(themeName).plist"
|
||||
let theme : NSMutableArray = NSMutableArray(contentsOfFile: plistPath) ?? NSMutableArray()
|
||||
if !theme.contains(path) {
|
||||
theme.add(path)
|
||||
let theme : NSMutableDictionary = NSMutableDictionary(contentsOfFile: plistPath) ?? NSMutableDictionary()
|
||||
if !(theme.allKeys as! [String]).contains(path) {
|
||||
theme.setObject(fileSha, forKey: path as NSString)
|
||||
}
|
||||
|
||||
|
||||
|
||||
if !theme.write(toFile: plistPath, atomically: false) {
|
||||
let errStr = "GI10, Error: can't write \(plistPath)"
|
||||
let se : Error = NSError(domain: self.errorDomain,
|
||||
@ -499,8 +541,8 @@ final class ThemeManager: NSObject, URLSessionDataDelegate {
|
||||
}
|
||||
|
||||
let plistPath : String = "\(themeManagerIndexDir)/Themes/\(theme).plist"
|
||||
|
||||
if let files : [String] = NSArray(contentsOfFile: plistPath) as? [String] {
|
||||
let themePlist = NSDictionary(contentsOfFile: plistPath)
|
||||
if let files : [String] = themePlist?.allKeys as? [String] {
|
||||
// ---------------------------------------
|
||||
let fc : Int = files.count
|
||||
if fc > 0 {
|
||||
@ -509,7 +551,7 @@ final class ThemeManager: NSObject, URLSessionDataDelegate {
|
||||
for i in 0..<fc {
|
||||
let file : String = files[i]
|
||||
// build the url
|
||||
let furl : String = "\(GitProtocol.https.rawValue)://raw.githubusercontent.com/CloverHackyColor/CloverThemes/master/\(file)"
|
||||
let furl : String = "\(GitProtocol.https.rawValue)://raw.githubusercontent.com/\(self.user)/\(self.repo)/master/\(file)"
|
||||
|
||||
if down == .thumbnail {
|
||||
if file != theme.addPath("screenshot.png")
|
||||
@ -589,7 +631,7 @@ final class ThemeManager: NSObject, URLSessionDataDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
public func signTheme(at path: String) {
|
||||
public func signTheme(at path: String) { // unused function
|
||||
if let sha : String = self.getSha() {
|
||||
let fileURL : URL = URL(fileURLWithPath: path)
|
||||
let data : Data? = sha.data(using: .utf8)
|
||||
@ -617,10 +659,81 @@ final class ThemeManager: NSObject, URLSessionDataDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
/// Check if a theme exist (in the current repository
|
||||
public func exist(theme: String) -> Bool {
|
||||
return fm.fileExists(atPath: "\(self.themeManagerIndexDir)/Themes/\(theme).plist")
|
||||
}
|
||||
|
||||
/// Check if a theme at the given path is up to date in the current repository. True if doesn't exists.
|
||||
public func isThemeUpToDate(at path : String) -> Bool {
|
||||
let theme = path.lastPath
|
||||
if !self.exist(theme: theme) {
|
||||
// if theme doesn't exist in the repository is up to date since is not part of it!
|
||||
return true
|
||||
}
|
||||
|
||||
let plistPath = "\(self.themeManagerIndexDir)/Themes/\(theme).plist"
|
||||
guard var plist = NSMutableDictionary(contentsOfFile: plistPath) as? [String : String] else {
|
||||
// We cannot load our generated file? :-(
|
||||
print("Error: Theme Manager can't load \(plistPath)")
|
||||
return true
|
||||
}
|
||||
|
||||
let enumerator = fm.enumerator(atPath: path)
|
||||
|
||||
while let file = enumerator?.nextObject() as? String {
|
||||
let fp = path.addPath(file)
|
||||
var isDir : ObjCBool = false
|
||||
fm.fileExists(atPath: fp, isDirectory: &isDir)
|
||||
|
||||
// don't check hidden files, like .DS_Store ;-)
|
||||
if !file.lastPath.hasPrefix(".") {
|
||||
/*
|
||||
Check only files.
|
||||
If extra directories exists inside the user theme it's not our business...
|
||||
*/
|
||||
if !isDir.boolValue {
|
||||
// ..it is if a file doesn't exist
|
||||
let key = theme.addPath(file)
|
||||
if let githubSha = plist[key] {
|
||||
// ok compare the sha1
|
||||
if let fileData = try? Data(contentsOf: URL(fileURLWithPath: fp)) {
|
||||
var gitdata = Data()
|
||||
let encoding : String.Encoding = .utf8
|
||||
gitdata.append("blob ".data(using: encoding)!)
|
||||
gitdata.append("\(fileData.count)".data(using: encoding)!)
|
||||
gitdata.append(0x00)
|
||||
gitdata.append(fileData)
|
||||
|
||||
let gitsha1 = gitdata.sha1
|
||||
if gitsha1 != githubSha {
|
||||
// sha doesn't match, this is a different file
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
print("Error: Theme Manager can't load \(fp)")
|
||||
return false
|
||||
}
|
||||
|
||||
plist[key] = nil // no longer needed
|
||||
} else {
|
||||
// file doesn't exist in the theme at repository
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
if We are here is because sha1 has been compared successfully
|
||||
for each file on the installed theme.
|
||||
If plist var no longer contains keys, it also means that all
|
||||
the files are existing on the installed theme.
|
||||
Otherwise fail!
|
||||
*/
|
||||
return plist.keys.count == 0
|
||||
}
|
||||
|
||||
public func optimizeTheme(at path: String, completion: @escaping (Error?) -> ()) {
|
||||
|
||||
DispatchQueue.global(priority: .background).async(execute: { () -> Void in
|
||||
|
@ -37,12 +37,12 @@
|
||||
<tableColumns>
|
||||
<tableColumn identifier="column1" width="147" minWidth="40" maxWidth="1000" id="SqG-sb-peF">
|
||||
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border">
|
||||
<font key="font" metaFont="label" size="11"/>
|
||||
<font key="font" metaFont="controlContent" size="11"/>
|
||||
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
|
||||
</tableHeaderCell>
|
||||
<textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" title="Text Cell" id="XIw-Cc-NAw">
|
||||
<font key="font" metaFont="label" size="13"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
@ -56,7 +56,7 @@
|
||||
<rect key="frame" x="0.0" y="0.0" width="147" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="Table View Cell" id="zkl-n1-vr4">
|
||||
<font key="font" metaFont="label" size="13"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
@ -86,7 +86,7 @@
|
||||
<rect key="frame" x="162" y="74" width="579" height="14"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" controlSize="small" lineBreakMode="truncatingTail" title="Description:" id="VVK-qM-R76">
|
||||
<font key="font" metaFont="label" size="11"/>
|
||||
<font key="font" metaFont="controlContent" size="11"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
@ -98,7 +98,7 @@
|
||||
<rect key="frame" x="162" y="51" width="579" height="15"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" controlSize="small" lineBreakMode="truncatingTail" title="Author:" id="nVY-gj-ELR">
|
||||
<font key="font" metaFont="label" size="11"/>
|
||||
<font key="font" metaFont="controlContent" size="11"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
@ -107,17 +107,12 @@
|
||||
</connections>
|
||||
</textField>
|
||||
<comboBox focusRingType="none" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="1Be-Yl-lqT">
|
||||
<rect key="frame" x="164" y="97" width="201" height="25"/>
|
||||
<rect key="frame" x="199" y="97" width="206" height="25"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<comboBoxCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" focusRingType="none" placeholderString="Theme" drawsBackground="YES" completes="NO" numberOfVisibleItems="5" id="ZdF-kp-eIO">
|
||||
<font key="font" metaFont="label" size="13"/>
|
||||
<comboBoxCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" focusRingType="none" placeholderString="Theme" drawsBackground="YES" usesDataSource="YES" numberOfVisibleItems="5" id="ZdF-kp-eIO">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
<objectValues>
|
||||
<string>Item 1</string>
|
||||
<string>Item 2</string>
|
||||
<string>Item 3</string>
|
||||
</objectValues>
|
||||
</comboBoxCell>
|
||||
<connections>
|
||||
<action selector="nameBoxSelected:" target="ClZ-60-myJ" id="rPH-oQ-4RO"/>
|
||||
@ -129,7 +124,7 @@
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="push" title="Install" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="hSu-fW-idj">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="label" size="13"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="InstallPressed:" target="ClZ-60-myJ" id="Phd-pp-aYa"/>
|
||||
@ -140,7 +135,7 @@
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<popUpButtonCell key="cell" type="push" title="Item 1" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="cP4-wD-4Ph" id="MEO-zC-Iak">
|
||||
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="label" size="13"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
<menu key="menu" id="fEx-Zt-ngB">
|
||||
<items>
|
||||
<menuItem title="Item 1" state="on" id="cP4-wD-4Ph"/>
|
||||
@ -165,11 +160,11 @@
|
||||
</webPreferences>
|
||||
</webView>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="qNn-1b-hdX">
|
||||
<rect key="frame" x="396" y="102" width="345" height="18"/>
|
||||
<rect key="frame" x="420" y="102" width="321" height="18"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="check" title="Show installed" bezelStyle="regularSquare" imagePosition="left" inset="2" id="PPl-2s-7pe">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="label" size="13"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="showInstalledThemes:" target="ClZ-60-myJ" id="mYF-2e-FAu"/>
|
||||
@ -180,7 +175,7 @@
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="push" title="Uninstall" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="Nxb-Kj-kDi">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="label" size="13"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="unInstallPressed:" target="ClZ-60-myJ" id="tVl-6l-eul"/>
|
||||
@ -191,12 +186,23 @@
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="push" title="Optimize" bezelStyle="rounded" alignment="center" borderStyle="border" inset="2" id="Sop-mp-zDW">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="label" size="13"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="optimizeThemePressed:" target="ClZ-60-myJ" id="eFv-na-WZg"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="x6y-uP-1AE">
|
||||
<rect key="frame" x="158" y="94" width="39" height="32"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="push" bezelStyle="rounded" image="NSRefreshFreestandingTemplate" imagePosition="only" alignment="center" borderStyle="border" imageScaling="axesIndependently" inset="2" id="bOt-6K-Swp">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="refreshIndexedThemesPressed:" target="ClZ-60-myJ" id="iRd-Gj-qZR"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
</view>
|
||||
<connections>
|
||||
@ -226,4 +232,7 @@
|
||||
</connections>
|
||||
</viewController>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="NSRefreshFreestandingTemplate" width="14" height="14"/>
|
||||
</resources>
|
||||
</document>
|
||||
|
@ -21,9 +21,14 @@ final class GradientView : NSView {
|
||||
}
|
||||
|
||||
final class ThemeManagerVC: NSViewController,
|
||||
NSTableViewDelegate, NSTableViewDataSource, WebFrameLoadDelegate, WebUIDelegate {
|
||||
NSTableViewDelegate,
|
||||
NSTableViewDataSource,
|
||||
WebFrameLoadDelegate,
|
||||
WebUIDelegate,
|
||||
NSComboBoxDelegate,
|
||||
NSComboBoxDataSource {
|
||||
var targetVolume : String? = nil
|
||||
|
||||
var themes : [String] = [String]()
|
||||
var manager : ThemeManager?
|
||||
@IBOutlet var installedThemesCheckBox : NSButton!
|
||||
|
||||
@ -62,19 +67,10 @@ NSTableViewDelegate, NSTableViewDataSource, WebFrameLoadDelegate, WebUIDelegate
|
||||
}
|
||||
self.loaded = true
|
||||
|
||||
/*
|
||||
let winImagePath = "/Library/Desktop Pictures/Ink Cloud.jpg"
|
||||
|
||||
if fm.fileExists(atPath: winImagePath) {
|
||||
let winImage = NSImage(byReferencingFile: winImagePath)
|
||||
let winImageSize = NSMakeSize(self.view.frame.width, self.view.frame.height)
|
||||
winImage?.size = winImageSize
|
||||
self.view.window?.backgroundColor = NSColor.init(patternImage: winImage!)
|
||||
}*/
|
||||
|
||||
self.view.window?.title = self.view.window!.title.locale
|
||||
let settingVC = AppSD.settingsWC?.contentViewController as? SettingsViewController
|
||||
settingVC?.themeUserField.isEnabled = false
|
||||
settingVC?.themeUserCBox.isEnabled = false
|
||||
settingVC?.themeRepoField.isEnabled = false
|
||||
self.webView.drawsBackground = false
|
||||
self.webView.uiDelegate = self
|
||||
@ -82,17 +78,17 @@ NSTableViewDelegate, NSTableViewDataSource, WebFrameLoadDelegate, WebUIDelegate
|
||||
self.webView.frameLoadDelegate = self
|
||||
self.webView.mainFrame.frameView.allowsScrolling = false
|
||||
|
||||
|
||||
localize(view: self.view)
|
||||
AppSD.isInstallerOpen = true
|
||||
settingVC?.disksPopUp.isEnabled = false
|
||||
settingVC?.updateCloverButton.isEnabled = false
|
||||
settingVC?.unmountButton.isEnabled = false
|
||||
|
||||
AppSD.themes.removeAll()
|
||||
self.nameBox.completes = true
|
||||
self.nameBox.delegate = self
|
||||
self.nameBox.dataSource = self
|
||||
self.nameBox.usesDataSource = true
|
||||
|
||||
self.nameBox.removeAllItems()
|
||||
self.sidebar.delegate = self
|
||||
self.sidebar.dataSource = self
|
||||
self.sidebar.backgroundColor = NSColor.clear
|
||||
@ -119,8 +115,14 @@ NSTableViewDelegate, NSTableViewDataSource, WebFrameLoadDelegate, WebUIDelegate
|
||||
}
|
||||
}
|
||||
|
||||
self.reloadThemes()
|
||||
}
|
||||
|
||||
func reloadThemes() {
|
||||
self.themes.removeAll()
|
||||
self.sidebar.reloadData()
|
||||
self.showIndexing()
|
||||
//return
|
||||
|
||||
let themeManagerIndexDir = NSHomeDirectory().addPath("Library/Application Support/CloverApp/Themeindex/\(AppSD.themeUser)_\(AppSD.themeRepo)")
|
||||
|
||||
self.manager = ThemeManager(user: AppSD.themeUser,
|
||||
@ -128,7 +130,6 @@ NSTableViewDelegate, NSTableViewDataSource, WebFrameLoadDelegate, WebUIDelegate
|
||||
basePath: themeManagerIndexDir,
|
||||
indexDir: themeManagerIndexDir,
|
||||
delegate: self)
|
||||
|
||||
/*
|
||||
1) immediately load indexed themes (if any).
|
||||
Fast if thumbnails already exists.
|
||||
@ -142,7 +143,7 @@ NSTableViewDelegate, NSTableViewDataSource, WebFrameLoadDelegate, WebUIDelegate
|
||||
2) download thumbnails.
|
||||
Slower if thumbnails didn't exist or themes never indexed.
|
||||
*/
|
||||
|
||||
|
||||
self.manager?.getThemes { (t) in
|
||||
let sorted = t.sorted()
|
||||
for t in sorted {
|
||||
@ -157,16 +158,48 @@ NSTableViewDelegate, NSTableViewDataSource, WebFrameLoadDelegate, WebUIDelegate
|
||||
if showInstalled {
|
||||
return AppSD.installedThemes
|
||||
}
|
||||
return AppSD.themes
|
||||
return self.themes
|
||||
}
|
||||
|
||||
func numberOfItems(in comboBox: NSComboBox) -> Int {
|
||||
return self.dataSource().count
|
||||
}
|
||||
|
||||
func comboBox(_ comboBox: NSComboBox, indexOfItemWithStringValue string: String) -> Int {
|
||||
return self.dataSource().firstIndex(of: string) ?? -1
|
||||
}
|
||||
func comboBox(_ comboBox: NSComboBox, objectValueForItemAt index: Int) -> Any? {
|
||||
return self.dataSource()[index]
|
||||
}
|
||||
|
||||
func comboBox(_ comboBox: NSComboBox, completedString string: String) -> String? {
|
||||
for theme in dataSource() {
|
||||
if theme.lowercased().hasPrefix(string.lowercased()) {
|
||||
return theme
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@IBAction func refreshIndexedThemesPressed(_ sender: NSButton!) {
|
||||
if let repoDir = self.manager?.themeManagerIndexDir {
|
||||
// delete old index
|
||||
if fm.fileExists(atPath: repoDir) {
|
||||
try? fm.removeItem(atPath: repoDir)
|
||||
}
|
||||
// re index the repository
|
||||
self.reloadThemes()
|
||||
} else {
|
||||
NSSound.beep()
|
||||
}
|
||||
}
|
||||
|
||||
@IBAction func showInstalledThemes(_ sender: NSButton!) {
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {
|
||||
let copy = self.manager!.getIndexedThemes().sorted() // in cases of low downloads
|
||||
self.nameBox.removeAllItems()
|
||||
self.sidebar.noteNumberOfRowsChanged()
|
||||
AppSD.installedThemes.removeAll()
|
||||
AppSD.themes.removeAll()
|
||||
self.themes.removeAll()
|
||||
|
||||
if sender.state == .on {
|
||||
if (self.targetVolume != nil && fm.fileExists(atPath: self.targetVolume!)) {
|
||||
@ -196,15 +229,13 @@ NSTableViewDelegate, NSTableViewDataSource, WebFrameLoadDelegate, WebUIDelegate
|
||||
} catch { }
|
||||
}
|
||||
AppSD.installedThemes = installed.sorted()
|
||||
self.nameBox.addItems(withObjectValues: installed.sorted())
|
||||
if installed.count == 0 {
|
||||
self.showNoThemes()
|
||||
}
|
||||
}
|
||||
self.showInstalled = true
|
||||
} else {
|
||||
AppSD.themes = copy
|
||||
self.nameBox.addItems(withObjectValues: copy.sorted())
|
||||
self.themes = copy
|
||||
self.showInstalled = false
|
||||
if copy.count == 0 {
|
||||
self.showNoThemes()
|
||||
@ -491,18 +522,15 @@ NSTableViewDelegate, NSTableViewDataSource, WebFrameLoadDelegate, WebUIDelegate
|
||||
}
|
||||
|
||||
func addRow(for theme: String) {
|
||||
let index = AppSD.themes.count
|
||||
AppSD.themes.append(theme)
|
||||
//if self.installedThemesCheckBox.state == .off {
|
||||
self.sidebar.beginUpdates()
|
||||
self.sidebar.insertRows(at: IndexSet(integer: index), withAnimation: .slideUp)
|
||||
self.sidebar.endUpdates()
|
||||
//}
|
||||
self.nameBox.addItem(withObjectValue: theme)
|
||||
let index = self.themes.count
|
||||
self.themes.append(theme)
|
||||
self.sidebar.beginUpdates()
|
||||
self.sidebar.insertRows(at: IndexSet(integer: index), withAnimation: .slideUp)
|
||||
self.sidebar.endUpdates()
|
||||
}
|
||||
|
||||
func add(theme: String) {
|
||||
if AppSD.themes.contains(theme) {
|
||||
if self.themes.contains(theme) {
|
||||
return
|
||||
}
|
||||
if let sha = self.manager?.getSha() {
|
||||
@ -562,8 +590,10 @@ NSTableViewDelegate, NSTableViewDataSource, WebFrameLoadDelegate, WebUIDelegate
|
||||
self.optimizeButton.isEnabled = false
|
||||
self.optimizeButton.state = .off
|
||||
let sr = self.sidebar.selectedRow
|
||||
|
||||
if sr >= 0 {
|
||||
if let v = self.sidebar.view(atColumn: 0, row: sr, makeIfNecessary: false) as? ThemeView {
|
||||
self.installButton.title = v.isUpToDate ? "Install".locale : "Update".locale
|
||||
if v.isInstalled {
|
||||
self.unistallButton.animator().isHidden = false
|
||||
self.unistallButton.isEnabled = true
|
||||
@ -638,6 +668,8 @@ NSTableViewDelegate, NSTableViewDataSource, WebFrameLoadDelegate, WebUIDelegate
|
||||
v.load()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.installButton.title = "Install".locale
|
||||
}
|
||||
}
|
||||
|
||||
@ -805,7 +837,7 @@ final class ThemeManagerWC: NSWindowController, NSWindowDelegate {
|
||||
settingVC?.updateCloverButton.isEnabled = true
|
||||
settingVC?.searchESPDisks()
|
||||
AppSD.isInstallerOpen = false
|
||||
settingVC?.themeUserField.isEnabled = true
|
||||
settingVC?.themeUserCBox.isEnabled = true
|
||||
settingVC?.themeRepoField.isEnabled = true
|
||||
self.window = nil
|
||||
self.close()
|
||||
|
@ -17,6 +17,7 @@ class ThemeView: NSView, WebFrameLoadDelegate, WebUIDelegate {
|
||||
var info : String?
|
||||
var row : Int
|
||||
var isInstalled = false
|
||||
var isUpToDate = true
|
||||
|
||||
public let webView: WebView = {
|
||||
let wv = WebView(frame: NSMakeRect(0, 0, 147, 82))
|
||||
@ -111,8 +112,10 @@ class ThemeView: NSView, WebFrameLoadDelegate, WebUIDelegate {
|
||||
}
|
||||
|
||||
func setInstalledStatus() {
|
||||
var installPath = ""
|
||||
if let vol = self.manager.delegate?.targetVolume {
|
||||
self.isInstalled = fm.fileExists(atPath: vol.addPath("EFI/CLOVER/themes").addPath(self.name))
|
||||
installPath = vol.addPath("EFI/CLOVER/themes").addPath(self.name)
|
||||
self.isInstalled = fm.fileExists(atPath: installPath)
|
||||
if (self.imagePath == nil) {
|
||||
if fm.fileExists(atPath: vol.addPath("EFI/CLOVER/themes").addPath(self.name).addPath("theme.svg")) {
|
||||
self.imagePath = vol.addPath("EFI/CLOVER/themes").addPath(self.name).addPath("theme.svg")
|
||||
@ -126,7 +129,8 @@ class ThemeView: NSView, WebFrameLoadDelegate, WebUIDelegate {
|
||||
|
||||
if let path = self.imagePath {
|
||||
if self.isInstalled {
|
||||
let icon = Bundle.main.path(forResource: "check", ofType: "png")
|
||||
self.isUpToDate = self.manager.isThemeUpToDate(at: installPath)
|
||||
let icon = Bundle.main.path(forResource: self.isUpToDate ? "check" : "update", ofType: "png")
|
||||
self.webView.mainFrame.loadHTMLString("""
|
||||
<html>
|
||||
<body>
|
||||
@ -138,6 +142,7 @@ class ThemeView: NSView, WebFrameLoadDelegate, WebUIDelegate {
|
||||
</html>
|
||||
""", baseURL: Bundle.main.bundleURL)
|
||||
} else {
|
||||
self.isUpToDate = true
|
||||
self.webView.mainFrame.loadHTMLString("""
|
||||
<html>
|
||||
<body>
|
||||
|
BIN
CloverApp/Clover/images/update.png
Normal file
BIN
CloverApp/Clover/images/update.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.1 KiB |
Loading…
Reference in New Issue
Block a user