[
  {
    "path": ".codeclimate.yml",
    "content": "engines:\n  tailor:\n    enabled: true\n\nratings:\n  paths:\n  - \"**.swift\"\n  exclude_paths: []\n"
  },
  {
    "path": ".gitignore",
    "content": "lokalise.cfg\n.DS_Store\nxcuserdata/\ncompile/\nbuild/\nDerivedData/\n*.xccheckout\nrelease/\ndebug.plist\nExamples/debug.html\nAerial/Source/Models/API/APISecrets.swift\n"
  },
  {
    "path": ".gitmodules",
    "content": "[submodule \"Extern/OAuthSwift\"]\n\tpath = Extern/OAuthSwift\n\turl = https://github.com/OAuthSwift/OAuthSwift.git\n\tbranch = 2.0.0\n\tignore = dirty\n"
  },
  {
    "path": ".swiftlint.yml",
    "content": "disabled_rules:\n  # Allow force-casting (e.g. `x as! UICollectionViewCell`).\n  # We may want to re-enable and address this rule.\n  - force_cast\n  # Allow `TODO` and `FIXME` comments.\n  - todo\n  # Allow the use of `let _ = <optional>`\n  - unused_optional_binding\n  # Allow the use of parantheses when calling methods with trailing completion closures\n  - empty_parentheses_with_trailing_closure\n  # We use enum \"namespaces\" which leads to nesting violations\n  - nesting\n  # Re-evalature to shorten functions up\n  - function_body_length\n  # Allow declaring operators without extra whitespace, like so: `func ==(_ lhs, ...)`\n  - operator_whitespace\n  - redundant_string_enum_value\n  - inclusive_language\n\nexcluded:\n  - Extern\n  \nopt_in_rules:\n  # Prefer checking `isEmpty` over `count > 0`\n  - empty_count\n\nfile_length:\n  warning: 1000\n  error: 2000\nline_length: 250\nidentifier_name:\n  min_length:\n    warning: 2\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: objective-c\nosx_image: xcode11.2\nbefore_install:\n  - pod repo update\nafter_success:\n  - bash <(curl -s https://codecov.io/bash) -J 'AerialApp'\nbefore_script:\n  - make lint\nscript:\n  - make test-travis\n"
  },
  {
    "path": "Aerial/App/AppDelegate.swift",
    "content": "//\n//  AppDelegate.swift\n//  Aerial Test\n//\n//  Created by John Coates on 10/23/15.\n//  Copyright © 2015 John Coates. All rights reserved.\n//\n\nimport Cocoa\n\n@NSApplicationMain\nclass AppDelegate: NSObject, NSApplicationDelegate {\n    // So this is where we come in, when compiled as an Application\n    override init() {\n        super.init()\n\n        // First thing : let our model know we are an app and not a screensaver !\n        Aerial.helper.appMode = true\n\n        let panelWindowController = PanelWindowController()\n        panelWindowController.showWindow(self)\n        panelWindowController.window?.makeKeyAndOrderFront(nil)\n    }\n}\n"
  },
  {
    "path": "Aerial/App/Resources/Assets.xcassets/Accent Color.colorset/Contents.json",
    "content": "{\n  \"colors\" : [\n    {\n      \"color\" : {\n        \"color-space\" : \"srgb\",\n        \"components\" : {\n          \"alpha\" : \"1.000\",\n          \"blue\" : \"0.517\",\n          \"green\" : \"0.585\",\n          \"red\" : \"0.176\"\n        }\n      },\n      \"idiom\" : \"universal\"\n    },\n    {\n      \"appearances\" : [\n        {\n          \"appearance\" : \"luminosity\",\n          \"value\" : \"dark\"\n        }\n      ],\n      \"color\" : {\n        \"color-space\" : \"srgb\",\n        \"components\" : {\n          \"alpha\" : \"1.000\",\n          \"blue\" : \"0.726\",\n          \"green\" : \"0.800\",\n          \"red\" : \"0.354\"\n        }\n      },\n      \"idiom\" : \"universal\"\n    }\n  ],\n  \"info\" : {\n    \"author\" : \"xcode\",\n    \"version\" : 1\n  }\n}\n"
  },
  {
    "path": "Aerial/App/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"mac\",\n      \"scale\" : \"1x\",\n      \"size\" : \"16x16\"\n    },\n    {\n      \"idiom\" : \"mac\",\n      \"scale\" : \"2x\",\n      \"size\" : \"16x16\"\n    },\n    {\n      \"idiom\" : \"mac\",\n      \"scale\" : \"1x\",\n      \"size\" : \"32x32\"\n    },\n    {\n      \"idiom\" : \"mac\",\n      \"scale\" : \"2x\",\n      \"size\" : \"32x32\"\n    },\n    {\n      \"idiom\" : \"mac\",\n      \"scale\" : \"1x\",\n      \"size\" : \"128x128\"\n    },\n    {\n      \"idiom\" : \"mac\",\n      \"scale\" : \"2x\",\n      \"size\" : \"128x128\"\n    },\n    {\n      \"idiom\" : \"mac\",\n      \"scale\" : \"1x\",\n      \"size\" : \"256x256\"\n    },\n    {\n      \"idiom\" : \"mac\",\n      \"scale\" : \"2x\",\n      \"size\" : \"256x256\"\n    },\n    {\n      \"idiom\" : \"mac\",\n      \"scale\" : \"1x\",\n      \"size\" : \"512x512\"\n    },\n    {\n      \"filename\" : \"icon-color-1-1024x1024-transparent.png\",\n      \"idiom\" : \"mac\",\n      \"scale\" : \"2x\",\n      \"size\" : \"512x512\"\n    }\n  ],\n  \"info\" : {\n    \"author\" : \"xcode\",\n    \"version\" : 1\n  }\n}\n"
  },
  {
    "path": "Aerial/App/Resources/Assets.xcassets/Contents.json",
    "content": "{\n  \"info\" : {\n    \"author\" : \"xcode\",\n    \"version\" : 1\n  }\n}\n"
  },
  {
    "path": "Aerial/App/Resources/Assets.xcassets/FirstPanelBackground.colorset/Contents.json",
    "content": "{\n  \"colors\" : [\n    {\n      \"color\" : {\n        \"color-space\" : \"srgb\",\n        \"components\" : {\n          \"alpha\" : \"1.000\",\n          \"blue\" : \"1.000\",\n          \"green\" : \"1.000\",\n          \"red\" : \"1.000\"\n        }\n      },\n      \"idiom\" : \"universal\"\n    },\n    {\n      \"appearances\" : [\n        {\n          \"appearance\" : \"luminosity\",\n          \"value\" : \"dark\"\n        }\n      ],\n      \"color\" : {\n        \"color-space\" : \"srgb\",\n        \"components\" : {\n          \"alpha\" : \"1.000\",\n          \"blue\" : \"37\",\n          \"green\" : \"35\",\n          \"red\" : \"33\"\n        }\n      },\n      \"idiom\" : \"universal\"\n    }\n  ],\n  \"info\" : {\n    \"author\" : \"xcode\",\n    \"version\" : 1\n  }\n}\n"
  },
  {
    "path": "Aerial/App/Resources/Base.lproj/MainMenu.xib",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.Cocoa.XIB\" version=\"3.0\" toolsVersion=\"21225\" targetRuntime=\"MacOSX.Cocoa\" propertyAccessControl=\"none\" useAutolayout=\"YES\" customObjectInstantitationMethod=\"direct\">\n    <dependencies>\n        <deployment version=\"101202\" identifier=\"macosx\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.CocoaPlugin\" version=\"21225\"/>\n        <capability name=\"documents saved in the Xcode 8 format\" minToolsVersion=\"8.0\"/>\n    </dependencies>\n    <objects>\n        <customObject id=\"-2\" userLabel=\"File's Owner\" customClass=\"NSApplication\">\n            <connections>\n                <outlet property=\"delegate\" destination=\"Voe-Tx-rLC\" id=\"GzC-gU-4Uq\"/>\n            </connections>\n        </customObject>\n        <customObject id=\"-1\" userLabel=\"First Responder\" customClass=\"FirstResponder\"/>\n        <customObject id=\"-3\" userLabel=\"Application\" customClass=\"NSObject\"/>\n        <customObject id=\"Voe-Tx-rLC\" customClass=\"AppDelegate\" customModule=\"AerialApp\" customModuleProvider=\"target\">\n            <connections>\n                <outlet property=\"window\" destination=\"QvC-M9-y7g\" id=\"gIp-Ho-8D9\"/>\n            </connections>\n        </customObject>\n        <customObject id=\"YLy-65-1bz\" customClass=\"NSFontManager\"/>\n        <menu title=\"Main Menu\" systemMenu=\"main\" id=\"AYu-sK-qS6\">\n            <items>\n                <menuItem title=\"AerialConfig\" id=\"1Xt-HY-uBw\">\n                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                    <menu key=\"submenu\" title=\"AerialConfig\" systemMenu=\"apple\" id=\"uQy-DD-JDr\">\n                        <items>\n                            <menuItem title=\"About AerialConfig\" id=\"5kV-Vb-QxS\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <connections>\n                                    <action selector=\"orderFrontStandardAboutPanel:\" target=\"-1\" id=\"Exp-CZ-Vem\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem isSeparatorItem=\"YES\" id=\"VOq-y0-SEH\"/>\n                            <menuItem title=\"Preferences…\" keyEquivalent=\",\" id=\"BOF-NM-1cW\"/>\n                            <menuItem isSeparatorItem=\"YES\" id=\"wFC-TO-SCJ\"/>\n                            <menuItem title=\"Services\" id=\"NMo-om-nkz\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <menu key=\"submenu\" title=\"Services\" systemMenu=\"services\" id=\"hz9-B4-Xy5\"/>\n                            </menuItem>\n                            <menuItem isSeparatorItem=\"YES\" id=\"4je-JR-u6R\"/>\n                            <menuItem title=\"Hide AerialConfig\" keyEquivalent=\"h\" id=\"Olw-nP-bQN\">\n                                <connections>\n                                    <action selector=\"hide:\" target=\"-1\" id=\"PnN-Uc-m68\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Hide Others\" keyEquivalent=\"h\" id=\"Vdr-fp-XzO\">\n                                <modifierMask key=\"keyEquivalentModifierMask\" option=\"YES\" command=\"YES\"/>\n                                <connections>\n                                    <action selector=\"hideOtherApplications:\" target=\"-1\" id=\"VT4-aY-XCT\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Show All\" id=\"Kd2-mp-pUS\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <connections>\n                                    <action selector=\"unhideAllApplications:\" target=\"-1\" id=\"Dhg-Le-xox\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem isSeparatorItem=\"YES\" id=\"kCx-OE-vgT\"/>\n                            <menuItem title=\"Quit AerialConfig\" keyEquivalent=\"q\" id=\"4sb-4s-VLi\">\n                                <connections>\n                                    <action selector=\"terminate:\" target=\"-1\" id=\"Te7-pn-YzF\"/>\n                                </connections>\n                            </menuItem>\n                        </items>\n                    </menu>\n                </menuItem>\n                <menuItem title=\"Edit\" id=\"Ely-96-cwI\">\n                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                    <menu key=\"submenu\" title=\"Edit\" id=\"hps-3b-qtH\">\n                        <items>\n                            <menuItem title=\"Undo\" keyEquivalent=\"z\" id=\"AZa-b7-JEi\">\n                                <connections>\n                                    <action selector=\"undo:\" target=\"-1\" id=\"F1I-HX-2LI\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Redo\" keyEquivalent=\"Z\" id=\"z8s-KR-qxL\">\n                                <connections>\n                                    <action selector=\"redo:\" target=\"-1\" id=\"vrh-8A-jrP\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem isSeparatorItem=\"YES\" id=\"8O0-qa-oC2\"/>\n                            <menuItem title=\"Cut\" keyEquivalent=\"x\" id=\"u6z-lC-eno\">\n                                <connections>\n                                    <action selector=\"cut:\" target=\"-1\" id=\"01I-WP-MKY\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Copy\" keyEquivalent=\"c\" id=\"fHG-NW-0z3\">\n                                <connections>\n                                    <action selector=\"copy:\" target=\"-1\" id=\"s4a-Cj-Acy\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Paste\" keyEquivalent=\"v\" id=\"sYN-V0-TdJ\">\n                                <connections>\n                                    <action selector=\"paste:\" target=\"-1\" id=\"55U-Jl-25y\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Paste and Match Style\" keyEquivalent=\"V\" id=\"aja-8e-dgu\">\n                                <modifierMask key=\"keyEquivalentModifierMask\" option=\"YES\" command=\"YES\"/>\n                                <connections>\n                                    <action selector=\"pasteAsPlainText:\" target=\"-1\" id=\"Tfs-Vv-6sM\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Delete\" id=\"yrU-MX-E7p\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <connections>\n                                    <action selector=\"delete:\" target=\"-1\" id=\"kLj-Wn-94S\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Select All\" keyEquivalent=\"a\" id=\"PNg-Ap-ics\">\n                                <connections>\n                                    <action selector=\"selectAll:\" target=\"-1\" id=\"Yba-wJ-PSK\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem isSeparatorItem=\"YES\" id=\"RoR-UE-hoY\"/>\n                            <menuItem title=\"Find\" id=\"vW6-hY-MBb\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <menu key=\"submenu\" title=\"Find\" id=\"Ver-gz-vxf\">\n                                    <items>\n                                        <menuItem title=\"Find…\" tag=\"1\" keyEquivalent=\"f\" id=\"SH6-Y1-RCn\">\n                                            <connections>\n                                                <action selector=\"performFindPanelAction:\" target=\"-1\" id=\"3Ky-oc-3OH\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Find and Replace…\" tag=\"12\" keyEquivalent=\"f\" id=\"kbM-Wh-CXk\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\" option=\"YES\" command=\"YES\"/>\n                                            <connections>\n                                                <action selector=\"performTextFinderAction:\" target=\"-1\" id=\"WOe-88-IYx\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Find Next\" tag=\"2\" keyEquivalent=\"g\" id=\"tLt-jX-W6u\">\n                                            <connections>\n                                                <action selector=\"performFindPanelAction:\" target=\"-1\" id=\"wOn-MG-aJ9\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Find Previous\" tag=\"3\" keyEquivalent=\"G\" id=\"FLM-v2-9VU\">\n                                            <connections>\n                                                <action selector=\"performFindPanelAction:\" target=\"-1\" id=\"vNk-lI-KrY\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Use Selection for Find\" tag=\"7\" keyEquivalent=\"e\" id=\"KED-o2-kES\">\n                                            <connections>\n                                                <action selector=\"performFindPanelAction:\" target=\"-1\" id=\"iE2-Sk-Y1f\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Jump to Selection\" keyEquivalent=\"j\" id=\"hx3-kP-qhB\">\n                                            <connections>\n                                                <action selector=\"centerSelectionInVisibleArea:\" target=\"-1\" id=\"G9A-VW-vqf\"/>\n                                            </connections>\n                                        </menuItem>\n                                    </items>\n                                </menu>\n                            </menuItem>\n                            <menuItem title=\"Spelling and Grammar\" id=\"rRo-Jn-UVa\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <menu key=\"submenu\" title=\"Spelling\" id=\"aoA-V7-nAF\">\n                                    <items>\n                                        <menuItem title=\"Show Spelling and Grammar\" keyEquivalent=\":\" id=\"i0r-K8-M7B\">\n                                            <connections>\n                                                <action selector=\"showGuessPanel:\" target=\"-1\" id=\"o1H-3B-zTq\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Check Document Now\" keyEquivalent=\";\" id=\"Utp-sk-ZNq\">\n                                            <connections>\n                                                <action selector=\"checkSpelling:\" target=\"-1\" id=\"4lE-58-CzY\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem isSeparatorItem=\"YES\" id=\"iRA-Bb-AOf\"/>\n                                        <menuItem title=\"Check Spelling While Typing\" id=\"pwo-Qg-oJR\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"toggleContinuousSpellChecking:\" target=\"-1\" id=\"fgA-sP-weF\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Check Grammar With Spelling\" id=\"tvK-Fx-9X7\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"toggleGrammarChecking:\" target=\"-1\" id=\"7PX-9g-HSb\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Correct Spelling Automatically\" id=\"WXd-nz-2VJ\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"toggleAutomaticSpellingCorrection:\" target=\"-1\" id=\"hND-cN-FCl\"/>\n                                            </connections>\n                                        </menuItem>\n                                    </items>\n                                </menu>\n                            </menuItem>\n                            <menuItem title=\"Substitutions\" id=\"qZk-DK-LJ2\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <menu key=\"submenu\" title=\"Substitutions\" id=\"buk-mV-Szi\">\n                                    <items>\n                                        <menuItem title=\"Show Substitutions\" id=\"uuW-7m-6fq\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"orderFrontSubstitutionsPanel:\" target=\"-1\" id=\"jKc-1S-kDY\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem isSeparatorItem=\"YES\" id=\"03X-EQ-kB2\"/>\n                                        <menuItem title=\"Smart Copy/Paste\" id=\"Sab-6D-ctk\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"toggleSmartInsertDelete:\" target=\"-1\" id=\"FtY-gg-piq\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Smart Quotes\" id=\"NBZ-hz-SgE\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"toggleAutomaticQuoteSubstitution:\" target=\"-1\" id=\"paF-wL-PNP\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Smart Dashes\" id=\"qDJ-ox-apW\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"toggleAutomaticDashSubstitution:\" target=\"-1\" id=\"EsJ-XT-H2z\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Smart Links\" id=\"puf-Wy-wRh\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"toggleAutomaticLinkDetection:\" target=\"-1\" id=\"H7m-TQ-z5r\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Data Detectors\" id=\"ZlN-Pp-V3w\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"toggleAutomaticDataDetection:\" target=\"-1\" id=\"dFC-9H-fe8\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Text Replacement\" id=\"U9I-vu-BCF\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"toggleAutomaticTextReplacement:\" target=\"-1\" id=\"RaR-Cg-QQY\"/>\n                                            </connections>\n                                        </menuItem>\n                                    </items>\n                                </menu>\n                            </menuItem>\n                            <menuItem title=\"Transformations\" id=\"YIb-H8-lLI\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <menu key=\"submenu\" title=\"Transformations\" id=\"K5e-xT-H5f\">\n                                    <items>\n                                        <menuItem title=\"Make Upper Case\" id=\"Dit-nN-q29\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"uppercaseWord:\" target=\"-1\" id=\"zBp-XU-qfZ\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Make Lower Case\" id=\"MFP-vp-qyh\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"lowercaseWord:\" target=\"-1\" id=\"PT3-O8-U6D\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Capitalize\" id=\"siS-MZ-CDU\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"capitalizeWord:\" target=\"-1\" id=\"R1r-R3-IeY\"/>\n                                            </connections>\n                                        </menuItem>\n                                    </items>\n                                </menu>\n                            </menuItem>\n                            <menuItem title=\"Speech\" id=\"vAf-Xs-OJA\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <menu key=\"submenu\" title=\"Speech\" id=\"qtJ-AJ-lgf\">\n                                    <items>\n                                        <menuItem title=\"Start Speaking\" id=\"YXV-gH-abS\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"startSpeaking:\" target=\"-1\" id=\"wZU-sl-bMV\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Stop Speaking\" id=\"5vG-ZP-DEH\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"stopSpeaking:\" target=\"-1\" id=\"Kjo-3s-VPE\"/>\n                                            </connections>\n                                        </menuItem>\n                                    </items>\n                                </menu>\n                            </menuItem>\n                        </items>\n                    </menu>\n                </menuItem>\n                <menuItem title=\"Window\" id=\"aUF-d1-5bR\">\n                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                    <menu key=\"submenu\" title=\"Window\" systemMenu=\"window\" id=\"Td7-aD-5lo\">\n                        <items>\n                            <menuItem title=\"Minimize\" keyEquivalent=\"m\" id=\"OY7-WF-poV\">\n                                <connections>\n                                    <action selector=\"performMiniaturize:\" target=\"-1\" id=\"VwT-WD-YPe\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Zoom\" id=\"R4o-n2-Eq4\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <connections>\n                                    <action selector=\"performZoom:\" target=\"-1\" id=\"DIl-cC-cCs\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem isSeparatorItem=\"YES\" id=\"eu3-7i-yIM\"/>\n                            <menuItem title=\"Bring All to Front\" id=\"LE2-aR-0XJ\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <connections>\n                                    <action selector=\"arrangeInFront:\" target=\"-1\" id=\"DRN-fu-gQh\"/>\n                                </connections>\n                            </menuItem>\n                        </items>\n                    </menu>\n                </menuItem>\n                <menuItem title=\"Help\" id=\"wpr-3q-Mcd\">\n                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                    <menu key=\"submenu\" title=\"Help\" systemMenu=\"help\" id=\"F2S-fz-NVQ\">\n                        <items>\n                            <menuItem title=\"AerialConfig Help\" keyEquivalent=\"?\" id=\"FKE-Sm-Kum\">\n                                <connections>\n                                    <action selector=\"showHelp:\" target=\"-1\" id=\"y7X-2Q-9no\"/>\n                                </connections>\n                            </menuItem>\n                        </items>\n                    </menu>\n                </menuItem>\n            </items>\n            <point key=\"canvasLocation\" x=\"-460\" y=\"78\"/>\n        </menu>\n        <window allowsToolTipsWhenApplicationIsInactive=\"NO\" autorecalculatesKeyViewLoop=\"NO\" releasedWhenClosed=\"NO\" animationBehavior=\"default\" titlebarAppearsTransparent=\"YES\" id=\"QvC-M9-y7g\">\n            <windowStyleMask key=\"styleMask\" titled=\"YES\" resizable=\"YES\" fullSizeContentView=\"YES\"/>\n            <windowPositionMask key=\"initialPositionMask\" leftStrut=\"YES\" rightStrut=\"YES\" topStrut=\"YES\" bottomStrut=\"YES\"/>\n            <rect key=\"contentRect\" x=\"335\" y=\"390\" width=\"1744\" height=\"1125\"/>\n            <rect key=\"screenRect\" x=\"0.0\" y=\"0.0\" width=\"2560\" height=\"1415\"/>\n            <view key=\"contentView\" id=\"EiT-Mj-1SZ\">\n                <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"1744\" height=\"1125\"/>\n                <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                <subviews>\n                    <customView fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"M0V-7R-ZSD\" customClass=\"AerialView\" customModule=\"AerialApp\" customModuleProvider=\"target\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"1744\" height=\"1125\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                    </customView>\n                </subviews>\n            </view>\n            <point key=\"canvasLocation\" x=\"492.5\" y=\"420\"/>\n        </window>\n    </objects>\n</document>\n"
  },
  {
    "path": "Aerial/App/Resources/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIconFile</key>\n\t<string></string>\n\t<key>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>APPL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>$(MARKETING_VERSION)</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleVersion</key>\n\t<string>$(CURRENT_PROJECT_VERSION)</string>\n\t<key>LSApplicationCategoryType</key>\n\t<string>public.app-category.utilities</string>\n\t<key>LSMinimumSystemVersion</key>\n\t<string>$(MACOSX_DEPLOYMENT_TARGET)</string>\n\t<key>NSAppTransportSecurity</key>\n\t<dict>\n\t\t<key>NSAllowsArbitraryLoads</key>\n\t\t<true/>\n\t</dict>\n\t<key>NSHumanReadableCopyright</key>\n\t<string>Copyright © 2015 John Coates. All rights reserved.</string>\n\t<key>NSLocationAlwaysUsageDescription</key>\n\t<string>Aerial uses location services to calculate Sunset and Sunrise times from your position</string>\n\t<key>NSLocationWhenInUseUsageDescription</key>\n\t<string>Aerial uses location services to calculate Sunset and Sunrise times from your position</string>\n\t<key>NSMainNibFile</key>\n\t<string>MainMenu</string>\n\t<key>NSPrincipalClass</key>\n\t<string>NSApplication</string>\n\t<key>SUFeedURL</key>\n\t<string>https://raw.githubusercontent.com/JohnCoates/Aerial/master/appcast.xml</string>\n\t<key>SUPublicEDKey</key>\n\t<string>fbiQGEFq55xl4bjwj2/SpIO4JMsKmEyhHEWlMMueyDY=</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "Aerial/Source/Controllers/CustomVideoController.swift",
    "content": "//\n//  CustomVideoController.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 21/05/2019.\n//  Copyright © 2019 John Coates. All rights reserved.\n//\n\nimport Foundation\nimport AppKit\nimport AVKit\n\nclass CustomVideoController: NSWindowController, NSWindowDelegate, NSDraggingDestination {\n    @IBOutlet var mainPanel: NSWindow!\n\n    // This is the panel workaround for Catalina\n    @IBOutlet var addFolderCatalinaPanel: NSPanel!\n    @IBOutlet var addFolderTextField: NSTextField!\n\n    @IBOutlet var folderOutlineView: NSOutlineView!\n    @IBOutlet var topPathControl: NSPathControl!\n\n    @IBOutlet var folderView: NSView!\n    @IBOutlet var fileView: NSView!\n    @IBOutlet var onboardingLabel: NSTextField!\n\n    @IBOutlet var folderShortNameTextField: NSTextField!\n    @IBOutlet var timePopUpButton: NSPopUpButton!\n    @IBOutlet var editPlayerView: AVPlayerView!\n    @IBOutlet var videoNameTextField: NSTextField!\n\n    @IBOutlet var poiTableView: NSTableView!\n    @IBOutlet var addPoi: NSButton!\n    @IBOutlet var removePoi: NSButton!\n\n    @IBOutlet var addPoiPopover: NSPopover!\n    @IBOutlet var timeTextField: NSTextField!\n    @IBOutlet var timeTextStepper: NSStepper!\n    @IBOutlet var timeTextFormatter: NumberFormatter!\n    @IBOutlet var descriptionTextField: NSTextField!\n\n    @IBOutlet var durationLabel: NSTextField!\n    @IBOutlet var resolutionLabel: NSTextField!\n    @IBOutlet var cvcMenu: NSMenu!\n\n    @IBOutlet var menuRemoveFolderAndVideos: NSMenuItem!\n    @IBOutlet var menuRemoveVideo: NSMenuItem!\n    var currentFolder: Folder?\n    var currentAsset: Asset?\n    var currentAssetDuration: Int?\n\n    var hasAwokenAlready = false\n    var sw: NSWindow?\n    var controller: SourcesViewController?\n\n    // MARK: - Lifecycle\n    required init?(coder: NSCoder) {\n        super.init(coder: coder)\n        debugLog(\"cvcinit\")\n    }\n\n    override init(window: NSWindow?) {\n        super.init(window: window)\n        self.sw = window\n        debugLog(\"cvcinit2\")\n    }\n\n    override func awakeFromNib() {\n        if !hasAwokenAlready {\n            debugLog(\"cvcawake\")\n            // self.menu = cvcMenu\n\n            folderOutlineView.dataSource = self\n            folderOutlineView.delegate = self\n            folderOutlineView.menu = cvcMenu\n            cvcMenu.delegate = self\n\n            if #available(OSX 10.13, *) {\n                folderOutlineView.registerForDraggedTypes([.fileURL, .URL])\n            } else {\n                // Fallback on earlier versions\n            }\n\n            poiTableView.dataSource = self\n            poiTableView.delegate = self\n\n            hasAwokenAlready = true\n            editPlayerView.player = AVPlayer()\n\n            NotificationCenter.default.addObserver(\n                self,\n                selector: #selector(self.windowWillClose(_:)),\n                name: NSWindow.willCloseNotification,\n                object: nil)\n        }\n    }\n\n    // We will receive this notification for every panel/window so we need to ensure it's the correct one\n    func windowWillClose(_ notification: Notification) {\n        if let wobj = notification.object as? NSPanel {\n            if wobj.title == \"Manage Custom Videos\" {\n                debugLog(\"Closing cvc\")\n                // TODO 2.0\n                /*\n                let manifestInstance = ManifestLoader.instance\n                manifestInstance.saveCustomVideos()\n\n                manifestInstance.addCallback { manifestVideos in\n                    if let contr = self.controller {\n                        contr.loaded(manifestVideos: [])\n                    }\n                }\n                manifestInstance.loadManifestsFromLoadedFiles() */\n            }\n        }\n    }\n\n    // This is the public function to make this visible\n    func show(sender: NSButton, controller: SourcesViewController) {\n        self.controller = controller\n        if !mainPanel.isVisible {\n            mainPanel.makeKeyAndOrderFront(sender)\n            folderOutlineView.expandItem(nil, expandChildren: true)\n            folderOutlineView.deselectAll(self)\n            folderView.isHidden = true\n            fileView.isHidden = true\n            topPathControl.isHidden = true\n        }\n    }\n\n    // MARK: - Edit Folders\n    @IBAction func folderNameChange(_ sender: NSTextField) {\n        if let folder = currentFolder {\n            folder.label = sender.stringValue\n            folderOutlineView.reloadData()\n        }\n    }\n\n    // MARK: - Add a new folder of videos to parse\n    @IBAction func addFolderButton(_ sender: NSButton) {\n        debugLog(\"addFolder\")\n        if #available(OSX 10.15, *) {\n            // On Catalina, we can't use NSOpenPanel right now\n            addFolderTextField.stringValue = \"\"\n            addFolderCatalinaPanel.makeKeyAndOrderFront(self)\n        } else {\n            let addFolderPanel = NSOpenPanel()\n            addFolderPanel.allowsMultipleSelection = false\n            addFolderPanel.canChooseDirectories = true\n            addFolderPanel.canCreateDirectories = false\n            addFolderPanel.canChooseFiles = false\n            addFolderPanel.title = \"Select a folder containing videos\"\n\n            addFolderPanel.begin { (response) in\n                if response.rawValue == NSFileHandlingPanelOKButton {\n                    self.processPathForVideos(url: addFolderPanel.url!)\n                }\n                addFolderPanel.close()\n            }\n        }\n    }\n\n    @IBAction func addFolderCatalinaConfirm(_ sender: Any) {\n        let strFolder = addFolderTextField.stringValue\n\n        if FileManager.default.fileExists(atPath: strFolder as String) {\n            self.processPathForVideos(url: URL(fileURLWithPath: strFolder, isDirectory: true))\n        }\n\n        addFolderCatalinaPanel.close()\n    }\n\n    func processPathForVideos(url: URL) {\n        debugLog(\"processing url for videos : \\(url) \")\n        let folderName = url.lastPathComponent\n        // let manifestInstance = ManifestLoader.instance\n\n        do {\n            let urls = try FileManager.default.contentsOfDirectory(at: url, includingPropertiesForKeys: nil, options: [.skipsHiddenFiles])\n            var assets = [VideoAsset]()\n\n            for lurl in urls {\n                if lurl.path.lowercased().hasSuffix(\".mp4\") || lurl.path.lowercased().hasSuffix(\".mov\") {\n                    assets.append(VideoAsset(accessibilityLabel: folderName,\n                                             id: NSUUID().uuidString,\n                                             title: lurl.lastPathComponent,\n                                             timeOfDay: \"day\",\n                                             scene: \"\",\n                                             pointsOfInterest: [:],\n                                             url4KHDR: \"\",\n                                             url4KSDR: lurl.path,\n                                             url1080H264: \"\",\n                                             url1080HDR: \"\",\n                                             url4KSDR120FPS: \"\",\n                                             url4KSDR240FPS: \"\",\n                                             url1080SDR: \"\",\n                                             url: \"\",\n                                             type: \"nature\"))\n                }\n            }\n\n            // ...\n            if SourceList.hasNamed(name: url.lastPathComponent) {\n                Aerial.helper.showInfoAlert(title: \"Source name mismatch\",\n                                     text: \"A source with this name already exists. Try renaming your folder and try again.\")\n            } else {\n                debugLog(\"Creating source \\(url.lastPathComponent)\")\n\n                // Generate and save the Source\n                let source = Source(name: url.lastPathComponent,\n                                    description: \"Local files from \\(url.path)\",\n                                    manifestUrl: \"manifest.json\",\n                                    type: .local,\n                                    scenes: [.nature],\n                                    isCachable: false,\n                                    license: \"\",\n                                    more: \"\")\n\n                SourceList.saveSource(source)\n\n                // Then the entries\n                let videoManifest = VideoManifest(assets: assets, initialAssetCount: 1, version: 1)\n\n                SourceList.saveEntries(source: source, manifest: videoManifest)\n            }\n/*\n            if let cvf = manifestInstance.customVideoFolders {\n                // check if we have this folder already ?\n                if !cvf.hasFolder(withUrl: url.path) && !assets.isEmpty {\n                    cvf.folders.append(Folder(url: url.path, label: folderName, assets: assets))\n                } else if !assets.isEmpty {\n                    // We need to append in place those that don't exist yet\n                    let folderIndex = cvf.getFolderIndex(withUrl: url.path)\n                    for asset in assets {\n                        if !cvf.folders[folderIndex].hasAsset(withUrl: asset.url) {\n                            cvf.folders[folderIndex].assets.append(asset)\n                        }\n                    }\n                }\n            } else {\n                // Create our initial CVF with the parsed folder\n                manifestInstance.customVideoFolders = CustomVideoFolders(folders: [Folder(url: url.path, label: folderName, assets: assets)])\n            }*/\n\n            folderOutlineView.reloadData()\n            folderOutlineView.expandItem(nil, expandChildren: true)\n            folderOutlineView.deselectAll(self)\n\n        } catch {\n            errorLog(\"Could not process directory\")\n        }\n    }\n\n    // MARK: - Edit Files\n    @IBAction func videoNameChange(_ sender: NSTextField) {\n        if let asset = currentAsset {\n            asset.accessibilityLabel = sender.stringValue\n            folderOutlineView.reloadData()\n        }\n    }\n\n    @IBAction func timePopUpChange(_ sender: NSPopUpButton) {\n        if let asset = currentAsset {\n            if sender.indexOfSelectedItem == 0 {\n                asset.time = \"day\"\n            } else {\n                asset.time = \"night\"\n            }\n        }\n    }\n\n    // MARK: - Add/Remove POIs\n    @IBAction func addPoiClick(_ sender: NSButton) {\n        addPoiPopover.show(relativeTo: sender.preparedContentRect, of: sender, preferredEdge: .maxY)\n    }\n\n    @IBAction func removePoiClick(_ sender: NSButton) {\n        if let asset = currentAsset {\n            let keys = asset.pointsOfInterest.keys.map { Int($0)!}.sorted()\n            asset.pointsOfInterest.removeValue(forKey: String(keys[poiTableView.selectedRow]))\n            poiTableView.reloadData()\n        }\n    }\n\n    @IBAction func addPoiValidate(_ sender: NSButton) {\n        if let asset = currentAsset {\n            if timeTextField.stringValue != \"\" && descriptionTextField.stringValue != \"\" {\n                if asset.pointsOfInterest[timeTextField.stringValue] == nil {\n                    asset.pointsOfInterest[timeTextField.stringValue] = descriptionTextField.stringValue\n\n                    // We also reset the popup so it's clean for next poi\n                    timeTextField.stringValue = \"\"\n                    descriptionTextField.stringValue = \"\"\n\n                    poiTableView.reloadData()\n                    addPoiPopover.close()\n                }\n            }\n        }\n    }\n\n    @IBAction func timeStepperChange(_ sender: NSStepper) {\n        if let player = editPlayerView.player {\n            player.seek(to: CMTime(seconds: Double(sender.intValue), preferredTimescale: 1))\n        }\n    }\n\n    @IBAction func timeTextChange(_ sender: NSTextField) {\n        if let player = editPlayerView.player {\n            player.seek(to: CMTime(seconds: Double(sender.intValue), preferredTimescale: 1))\n        }\n    }\n\n    @IBAction func tableViewTimeField(_ sender: NSTextField) {\n        if let asset = currentAsset {\n            if poiTableView.selectedRow != -1 {\n                let keys = asset.pointsOfInterest.keys.map { Int($0)!}.sorted()\n                asset.pointsOfInterest.switchKey(fromKey: String(keys[poiTableView.selectedRow]), toKey: sender.stringValue)\n            }\n        }\n    }\n\n    @IBAction func tableViewDescField(_ sender: NSTextField) {\n        if let asset = currentAsset {\n            if poiTableView.selectedRow != -1 {\n                let keys = asset.pointsOfInterest.keys.map { Int($0)!}.sorted()\n                asset.pointsOfInterest[String(keys[poiTableView.selectedRow])] = sender.stringValue\n            }\n        }\n    }\n\n    // MARK: - Context menu\n    @IBAction func menuRemoveFolderAndVideoClick(_ sender: NSMenuItem) {\n        if let folder = sender.representedObject as? Folder {\n            let manifestInstance = ManifestLoader.instance\n\n            if let cvf = manifestInstance.customVideoFolders {\n                cvf.folders.remove(at: cvf.getFolderIndex(withUrl: folder.url))\n            }\n        }\n        folderOutlineView.reloadData()\n    }\n\n    @IBAction func menuRemoveVideoClick(_ sender: NSMenuItem) {\n        if let asset = sender.representedObject as? Asset {\n            let manifestInstance = ManifestLoader.instance\n\n            if let cvf = manifestInstance.customVideoFolders {\n                for fld in cvf.folders {\n                    let index = fld.getAssetIndex(withUrl: asset.url)\n                    if index > -1 {\n                        fld.assets.remove(at: index)\n                    }\n                }\n            }\n        }\n        folderOutlineView.reloadData()\n    }\n}\n\n// MARK: - Data source for side bar\nextension CustomVideoController: NSOutlineViewDataSource {\n    // Find and return the child of an item. If item == nil, we need to return a child of the\n    // root node otherwise we find and return the child of the parent node indicated by 'item'\n    func outlineView(_ outlineView: NSOutlineView, child index: Int, ofItem item: Any?) -> Any {\n        let manifestInstance = ManifestLoader.instance\n\n        if let source = item as? Source {\n            return VideoList.instance.videos.filter({ $0.source.name == source.name })[index]\n        }\n\n        // Return a source\n        return SourceList.foundSources.filter({ $0.type == .local })[index]\n    }\n\n    // Tell the view controller whether an item can be expanded (i.e. it has children) or not\n    // (i.e. it doesn't)\n    func outlineView(_ outlineView: NSOutlineView, isItemExpandable item: Any) -> Bool {\n        // A folder may have childs if it's not empty\n        if let folder = item as? Folder {\n            return !folder.assets.isEmpty\n        }\n\n        // But not assets\n        return false\n    }\n\n    // Tell the view how many children an item has\n    func outlineView(_ outlineView: NSOutlineView, numberOfChildrenOfItem item: Any?) -> Int {\n        let manifestInstance = ManifestLoader.instance\n\n        // A folder may have childs\n        if let source = item as? Source {\n            return VideoList.instance.videos.filter({ $0.source.name == source.name }).count\n        }\n\n        return SourceList.foundSources.filter({ $0.type == .local }).count\n\n    }\n}\n\n// MARK: - Delegate for side bar\n\nextension CustomVideoController: NSOutlineViewDelegate {\n    // Add text to the view. 'item' will either be a Creature object or a string. If it's the former we just\n    // use the 'type' attribute otherwise we downcast it to a string and use that instead.\n    func outlineView(_ outlineView: NSOutlineView, viewFor tableColumn: NSTableColumn?, item: Any) -> NSView? {\n        var text = \"\"\n\n        if let source = item as? Source {\n            text = source.name\n        } else if let video = item as? AerialVideo {\n            text = video.name\n        }\n\n        // Create our table cell -- note the reference to 'creatureCell' that we set when configuring the table cell\n        let tableCell = outlineView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: \"folderCell\"), owner: nil) as! NSTableCellView\n        tableCell.textField!.stringValue = text\n        return tableCell\n    }\n\n    // We update our view here when an item is selected\n    func outlineView(_ outlineView: NSOutlineView, shouldSelectItem item: Any) -> Bool {\n        debugLog(\"selected \\(item)\")\n\n        if let source = item as? Source {\n            topPathControl.isHidden = false\n            folderView.isHidden = false\n            fileView.isHidden = true\n            onboardingLabel.isHidden = true\n\n            topPathControl.url = URL(fileURLWithPath: source.manifestUrl)\n            folderShortNameTextField.stringValue = source.description\n            currentAsset = nil\n            currentFolder = nil // folder\n        } else if let file = item as? Asset {\n            topPathControl.isHidden = false\n            folderView.isHidden = true\n            fileView.isHidden = false\n            onboardingLabel.isHidden = true\n\n            topPathControl.url = URL(fileURLWithPath: file.url)\n            videoNameTextField.stringValue = file.accessibilityLabel\n            if file.time == \"day\" {\n                timePopUpButton.selectItem(at: 0)\n            } else {\n                timePopUpButton.selectItem(at: 1)\n            }\n            currentFolder = nil\n            currentAsset = file     // We use this later to populate the table view\n            removePoi.isEnabled = false\n\n            if let player = editPlayerView.player {\n                let localitem = AVPlayerItem(url: URL(fileURLWithPath: file.url))\n                currentAssetDuration = Int(localitem.asset.duration.convertScale(1, method: .default).value)\n                let currentResolution = getResolution(asset: localitem.asset)\n                let crString = String(Int(currentResolution.width)) + \"x\" + String(Int(currentResolution.height))\n\n                timeTextStepper.minValue = 0\n                timeTextStepper.maxValue = Double(currentAssetDuration!)\n                timeTextFormatter.minimum = 0\n                timeTextFormatter.maximum = NSNumber(value: currentAssetDuration!)\n\n                durationLabel.stringValue = String(currentAssetDuration!) + \" seconds\"\n                resolutionLabel.stringValue = crString\n\n                player.replaceCurrentItem(with: localitem)\n            }\n\n            poiTableView.reloadData()\n        } else {\n            topPathControl.isHidden = true\n            folderView.isHidden = true\n            fileView.isHidden = true\n            onboardingLabel.isHidden = false\n        }\n\n        return true\n    }\n\n    func getResolution(asset: AVAsset) -> CGSize {\n        guard let track = asset.tracks(withMediaType: AVMediaType.video).first else { return CGSize.zero }\n        let size = track.naturalSize.applying(track.preferredTransform)\n        return CGSize(width: abs(size.width), height: abs(size.height))\n    }\n\n    func outlineView(_ outlineView: NSOutlineView, validateDrop info: NSDraggingInfo, proposedItem item: Any?, proposedChildIndex index: Int) -> NSDragOperation {\n        return NSDragOperation.copy\n    }\n\n    func outlineView(_ outlineView: NSOutlineView, acceptDrop info: NSDraggingInfo, item: Any?, childIndex index: Int) -> Bool {\n\n        if let items = info.draggingPasteboard.pasteboardItems {\n            for item in items {\n                if #available(OSX 10.13, *) {\n                    if let str = item.string(forType: .fileURL) {\n                        let surl = URL(fileURLWithPath: str).standardized\n                        debugLog(\"received drop \\(surl)\")\n                        if surl.isDirectory {\n                            debugLog(\"processing dir\")\n                            self.processPathForVideos(url: surl)\n                        }\n                    }\n                } else {\n                    // Fallback on earlier versions\n                }\n            }\n        }\n        return true\n    }\n}\n\n// MARK: - Extension for poi table view\nextension CustomVideoController: NSTableViewDataSource, NSTableViewDelegate {\n    // currentAsset contains the selected video asset\n\n    func numberOfRows(in tableView: NSTableView) -> Int {\n        if let asset = currentAsset {\n            return asset.pointsOfInterest.count\n        } else {\n            return 0\n        }\n    }\n\n    // This is where we populate the tableview\n    func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {\n        if let asset = currentAsset {\n            var text: String\n            if tableColumn!.identifier.rawValue == \"timeColumn\" {\n                let keys = asset.pointsOfInterest.keys.map { Int($0)!}.sorted()\n                text = String(keys[row])\n            } else {\n                let keys = asset.pointsOfInterest.keys.map { Int($0)!}.sorted()\n                text = asset.pointsOfInterest[String(keys[row])]!\n            }\n\n            if let cell = tableView.makeView(withIdentifier: tableColumn!.identifier, owner: self) as? NSTableCellView {\n                cell.textField?.stringValue = text\n                cell.imageView?.image = nil\n                return cell\n            }\n        }\n\n        return nil\n    }\n\n    func tableViewSelectionDidChange(_ notification: Notification) {\n        if let asset = currentAsset {\n            if poiTableView.selectedRow >= 0 {\n                removePoi.isEnabled = true\n\n                let keys = asset.pointsOfInterest.keys.map { Int($0)!}.sorted()\n                if let player = editPlayerView.player {\n                    player.seek(to: CMTime(seconds: Double(keys[poiTableView.selectedRow]), preferredTimescale: 1))\n                }\n            } else {\n                removePoi.isEnabled = false\n            }\n        }\n    }\n\n}\n\nextension Dictionary {\n    mutating func switchKey(fromKey: Key, toKey: Key) {\n        if let entry = removeValue(forKey: fromKey) {\n            self[toKey] = entry\n        }\n    }\n}\n\nextension URL {\n    /*var isDirectory: Bool? {\n        do {\n            let values = try self.resourceValues(\n                forKeys: Set([URLResourceKey.isDirectoryKey])\n            )\n            return values.isDirectory\n        } catch { return nil }\n    }*/\n\n    var isDirectory: Bool {\n        return (try? resourceValues(forKeys: [.isDirectoryKey]))?.isDirectory == true\n    }\n    var subDirectories: [URL] {\n        guard isDirectory else { return [] }\n        return (try? FileManager.default.contentsOfDirectory(at: self,\n                    includingPropertiesForKeys: nil,\n                    options: [.skipsHiddenFiles]).filter(\\.isDirectory)) ?? []\n    }\n}\n\nextension CustomVideoController: NSMenuDelegate {\n    func menuNeedsUpdate(_ menu: NSMenu) {\n        let row = folderOutlineView.clickedRow\n        guard row != -1 else { return }\n        let rowItem = folderOutlineView.item(atRow: row)\n\n        if (rowItem as? Folder) != nil {\n            menuRemoveVideo.isHidden = true\n            menuRemoveFolderAndVideos.isHidden = false\n        } else if (rowItem as? Asset) != nil {\n            menuRemoveVideo.isHidden = false\n            menuRemoveFolderAndVideos.isHidden = true\n        }\n\n        // Mark the clicked item here\n        for item in menu.items {\n            item.representedObject = rowItem\n        }\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Header.h",
    "content": "//\n//  Header.h\n//  Aerial\n//\n//  Created by Guillaume Louel on 26/07/2023.\n//  Copyright © 2023 Guillaume Louel. All rights reserved.\n//\n\n#ifndef Header_h\n#define Header_h\n\n\n#endif /* Header_h */\n"
  },
  {
    "path": "Aerial/Source/Models/API/Forecast.swift",
    "content": "//\n//  Forecast.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 26/04/2021.\n//  Copyright © 2021 Guillaume Louel. All rights reserved.\n//\n// This file was generated from JSON Schema using quicktype, do not modify it directly.\n// To parse the JSON, add this file to your project and do:\n//\n//   let forecast = try? newJSONDecoder().decode(Forecast.self, from: jsonData)\n\nimport Foundation\n\n// MARK: - Forecast\nstruct ForecastElement: Codable {\n    let cod: String?\n    let message, cnt: Int?\n    let list: [FList]?\n    let city: City?\n}\n\n// MARK: - City\nstruct City: Codable {\n    let id: Int?\n    let name: String?\n    let coord: Coord?\n    let country: String?\n    let population, timezone, sunrise, sunset: Int?\n}\n\n// MARK: - Coord\nstruct Coord: Codable {\n    let lat, lon: Double?\n}\n\n// MARK: - List\nstruct FList: Codable {\n    let dt: Int?\n    let main: MainClass?\n    let weather: [OWWeather]?\n    let clouds: Clouds?\n    let wind: Wind?\n    let visibility: Int?\n    let pop: Double?\n    let sys: Sys?\n    let dtTxt: String?\n    let rain: Rain?\n\n    enum CodingKeys: String, CodingKey {\n        case dt, main, weather, clouds, wind, visibility, pop, sys\n        case dtTxt = \"dt_txt\"\n        case rain\n    }\n}\n\n// MARK: - Clouds\nstruct Clouds: Codable {\n    let all: Int?\n}\n\n// MARK: - MainClass\nstruct MainClass: Codable {\n    let temp, feelsLike, tempMin, tempMax: Double?\n    let pressure, seaLevel, grndLevel, humidity: Int?\n    let tempKf: Double?\n\n    enum CodingKeys: String, CodingKey {\n        case temp\n        case feelsLike = \"feels_like\"\n        case tempMin = \"temp_min\"\n        case tempMax = \"temp_max\"\n        case pressure\n        case seaLevel = \"sea_level\"\n        case grndLevel = \"grnd_level\"\n        case humidity\n        case tempKf = \"temp_kf\"\n    }\n}\n\n// MARK: - Rain\nstruct Rain: Codable {\n    let the3H: Double?\n\n    enum CodingKeys: String, CodingKey {\n        case the3H = \"3h\"\n    }\n}\n\n// MARK: - Sys\nstruct Sys: Codable {\n    let pod: String?\n}\n\n// MARK: - ForecastError\nstruct ForecastError: Codable {\n    let cod, message: String?\n}\n\n// MARK: - Wind\nstruct Wind: Codable {\n    let speed: Double?\n    let deg: Int?\n    let gust: Double?\n}\n\nstruct Forecast {\n\n    static var testJson = \"\"\n\n    static func getUnits() -> String {\n        if PrefsInfo.weather.degree == .celsius {\n            return \"metric\"\n        } else {\n            return \"imperial\"\n        }\n    }\n\n    static func getShortcodeLanguage() -> String {\n        // Those are the languages supported by OpenWeather\n        let weatherLanguages = [\"af\", \"al\", \"ar\", \"az\", \"bg\", \"ca\", \"cz\", \"da\", \"de\", \"el\", \"en\",\n                                \"eu\", \"fa\", \"fi\", \"fr\", \"gl\", \"he\", \"hi\", \"hr\", \"hu\", \"id\", \"it\",\n                                \"ja\", \"kr\", \"la\", \"lt\", \"mk\", \"no\", \"nl\", \"pl\", \"pt\", \"pt_br\", \"ro\",\n                                \"ru\", \"sv\", \"sk\", \"sl\", \"es\", \"sr\", \"th\", \"tr\", \"uk\", \"vi\", \"zh_cn\",\n                                \"zh_tw\", \"zu\" ]\n\n        if PrefsAdvanced.ciOverrideLanguage == \"\" {\n            let bestMatchedLanguage = Bundle.preferredLocalizations(from: weatherLanguages, forPreferences: Locale.preferredLanguages).first\n            if let match = bestMatchedLanguage {\n                debugLog(\"Best matched language : \\(match)\")\n                return match\n            }\n        } else {\n            debugLog(\"Overrode matched language : \\(PrefsAdvanced.ciOverrideLanguage)\")\n            return PrefsAdvanced.ciOverrideLanguage\n        }\n\n        // We fallback here if nothing works\n        return \"en\"\n    }\n\n    static func makeUrl(lat: String, lon: String) -> String {\n        return \"https://api.openweathermap.org/data/2.5/forecast\"\n            + \"?lat=\\(lat)&lon=\\(lon)\"\n            + \"&units=\\(getUnits())\"\n            + \"&lang=\\(getShortcodeLanguage())\"\n            + \"&APPID=\\(APISecrets.openWeatherAppId)\"\n    }\n\n    static func makeUrl(location: String) -> String {\n        let nloc = location.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!\n\n        return \"https://api.openweathermap.org/data/2.5/forecast\"\n            + \"?q=\\(nloc)\"\n            + \"&units=\\(getUnits())\"\n            + \"&lang=\\(getShortcodeLanguage())\"\n            + \"&APPID=\\(APISecrets.openWeatherAppId)\"\n    }\n\n    // swiftlint:disable:next cyclomatic_complexity\n    static func fetch(completion: @escaping(Result<ForecastElement, NetworkError>) -> Void) {\n        guard testJson == \"\" else {\n            let jsonData = testJson.data(using: .utf8)!\n\n            if let forecast = try? newJSONDecoder().decode(ForecastElement.self, from: jsonData) {\n                completion(.success(forecast))\n            } else {\n                completion(.failure(.unknown))\n            }\n\n            return\n        }\n\n        if PrefsInfo.weather.locationMode == .useCurrent {\n            let location = Locations.sharedInstance\n\n            location.getCoordinates(failure: { (_) in\n                completion(.failure(.unknown))\n            }, success: { (coordinates) in\n                let lat = String(format: \"%.2f\", coordinates.latitude)\n                let lon = String(format: \"%.2f\", coordinates.longitude)\n                debugLog(\"=== OF: Starting locationMode\")\n\n                fetchData(from: makeUrl(lat: lat, lon: lon)) { result in\n                    switch result {\n                    case .success(let jsonString):\n                        let jsonData = jsonString.data(using: .utf8)!\n\n                        if let forecast = try? newJSONDecoder().decode(ForecastElement.self, from: jsonData) {\n                            completion(.success(forecast))\n                        } else if (try? newJSONDecoder().decode(ForecastError.self, from: jsonData)) != nil {\n                            completion(.failure(.cityNotFound))\n                        } else {\n                            completion(.failure(.unknown))\n                        }\n                    case .failure(let error):\n                        completion(.failure(.unknown))\n                        print(error.localizedDescription)\n                    }\n                }\n            })\n        } else {\n            // Just in case, we add a failsafe\n            if PrefsInfo.weather.locationString == \"\" {\n                PrefsInfo.weather.locationString = \"Paris, FR\"\n            }\n            debugLog(\"=== OF: Starting manual mode\")\n\n            fetchData(from: makeUrl(location: PrefsInfo.weather.locationString)) { result in\n                switch result {\n                case .success(let jsonString):\n                    let jsonData = jsonString.data(using: .utf8)!\n\n                    if let forecast = try? newJSONDecoder().decode(ForecastElement.self, from: jsonData) {\n                        completion(.success(forecast))\n                    } else if (try? newJSONDecoder().decode(ForecastError.self, from: jsonData)) != nil {\n                        completion(.failure(.cityNotFound))\n                    } else {\n                        completion(.failure(.unknown))\n                    }\n                case .failure(_):\n                    completion(.failure(.unknown))\n                }\n            }\n        }\n    }\n\n    private static func fetchData(from urlString: String, completion: @escaping (Result<String, NetworkError>) -> Void) {\n        // check the URL is OK, otherwise return with a failure\n        guard let url = URL(string: urlString) else {\n            completion(.failure(.badURL))\n            return\n        }\n\n        URLSession.shared.dataTask(with: url) { data, _, error in\n            // the task has completed – push our work back to the main thread\n            DispatchQueue.main.async {\n                if let data = data {\n                    // success: convert the data to a string and send it back\n                    let stringData = String(decoding: data, as: UTF8.self)\n                    completion(.success(stringData))\n                } else if error != nil {\n                    // any sort of network failure\n                    completion(.failure(.requestFailed))\n                } else {\n                    // this ought not to be possible, yet here we are\n                    completion(.failure(.unknown))\n                }\n            }\n        }.resume()\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Models/API/GeoCoding.swift",
    "content": "//\n//  GeoCoding.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 22/04/2021.\n//  Copyright © 2021 Guillaume Louel. All rights reserved.\n//\n\nimport Foundation\n\n// MARK: - GeoCodingElement\nstruct GeoCodingElement: Codable {\n    let name: String?\n    let lat, lon: Double?\n    let country, state: String?\n\n    enum CodingKeys: String, CodingKey {\n        case name\n        case lat, lon, country, state\n    }\n}\ntypealias GeoCodingArray = [GeoCodingElement]\n\nstruct GeoLocation {\n    let lat, lon: String\n}\n\nstruct GeoCoding {\n\n    static func fetch(completion: @escaping(Result<GeoLocation, NetworkError>) -> Void) {\n        // Check if we already have a geocoded location for this ?\n        if PrefsTime.geocodedString == PrefsInfo.weather.locationString {\n            debugLog(\"returning cached location from previous geocoding\")\n            let lat = String(format: \"%.2f\", PrefsTime.cachedLatitude)\n            let lon = String(format: \"%.2f\", PrefsTime.cachedLongitude)\n\n            completion(.success(GeoLocation(lat: lat, lon: lon)))\n        } else {\n            // Seriously, please use Location services...\n            debugLog(\"looking for location through geocoding api\")\n            // Just in case, we add a ugly failsafe\n            if PrefsInfo.weather.locationString == \"\" {\n                PrefsInfo.weather.locationString = \"Paris, FR\"\n            }\n\n            fetchData(from: makeUrl()) { result in\n                switch result {\n                case .success(let jsonString):\n                    let jsonData = jsonString.data(using: .utf8)!\n\n                    if let geoEntity = try? newJSONDecoder().decode(GeoCodingArray.self, from: jsonData) {\n                        if geoEntity.count >= 1 {\n                            let lat = String(format: \"%.2f\", geoEntity[0].lat!)\n                            let lon = String(format: \"%.2f\", geoEntity[0].lon!)\n\n                            // Let's save for next time\n                            PrefsTime.geocodedString = PrefsInfo.weather.locationString\n                            PrefsTime.cachedLatitude = geoEntity[0].lat!\n                            PrefsTime.cachedLongitude = geoEntity[0].lon!\n\n                            completion(.success(GeoLocation(lat: lat, lon: lon)))\n                        } else {\n                            completion(.failure(.unknown))\n\n                        }\n                    } else {\n                        completion(.failure(.unknown))\n                    }\n                case .failure(_):\n                    completion(.failure(.unknown))\n                }\n            }\n        }\n    }\n\n    static func makeUrl() -> String {\n        let nloc = PrefsInfo.weather.locationString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!\n        return \"https://api.openweathermap.org/geo/1.0/direct\"\n            + \"?q=\\(nloc)\"\n            + \"&appid=\\(APISecrets.openWeatherAppId)\"\n    }\n\n    private static func fetchData(from urlString: String, completion: @escaping (Result<String, NetworkError>) -> Void) {\n        // check the URL is OK, otherwise return with a failure\n        guard let url = URL(string: urlString) else {\n            completion(.failure(.badURL))\n            return\n        }\n\n        URLSession.shared.dataTask(with: url) { data, _, error in\n            // the task has completed – push our work back to the main thread\n            DispatchQueue.main.async {\n                if let data = data {\n                    // success: convert the data to a string and send it back\n                    let stringData = String(decoding: data, as: UTF8.self)\n                    completion(.success(stringData))\n                } else if error != nil {\n                    // any sort of network failure\n                    completion(.failure(.requestFailed))\n                } else {\n                    // this ought not to be possible, yet here we are\n                    completion(.failure(.unknown))\n                }\n            }\n        }.resume()\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Models/API/OneCall.swift",
    "content": "//\n//  OWOneCall.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 23/03/2021.\n//  Copyright © 2021 Guillaume Louel. All rights reserved.\n//\n// This file was generated from JSON Schema using quicktype, do not modify it directly.\n// To parse the JSON, add this file to your project and do:\n//\n//   let oCOneCall = try? newJSONDecoder().decode(OCOneCall.self, from: jsonData)\n\nimport Foundation\n\n// MARK: - OCOneCall\nstruct OCOneCall: Codable {\n    let lat, lon: Double?\n    let timezone: String?\n    let timezoneOffset: Int?\n    let current: OCCurrent?\n    let minutely: [OCMinutely]?\n    let hourly: [OCCurrent]?\n    let daily: [OCDaily]?\n\n    enum CodingKeys: String, CodingKey {\n        case lat, lon, timezone\n        case timezoneOffset = \"timezone_offset\"\n        case current, minutely, hourly, daily\n    }\n\n    // We round them down a bit as openweather provides up to two decimal point precision\n    mutating func processTemperatures() {\n        /*\n        guard main != nil else {\n            return\n        }\n\n        if PrefsInfo.weather.degree == .celsius {\n            main!.temp = main!.temp.rounded(toPlaces: 1)\n            main!.feelsLike = main!.feelsLike.rounded(toPlaces: 1)\n        } else {\n            main!.temp = main!.temp.rounded()\n            main!.feelsLike = main!.feelsLike.rounded()\n        }*/\n    }\n}\n\n// MARK: - OCCurrent\nstruct OCCurrent: Codable {\n    let dt, sunrise, sunset: Int?\n    let temp, feelsLike: Double?\n    let pressure, humidity: Int?\n    let dewPoint, uvi: Double?\n    let clouds, visibility: Int?\n    let windSpeed: Double?\n    let windDeg: Int?\n    let weather: [OWWeather]?\n    let windGust, pop: Double?\n    let rain: OCRain?\n\n    enum CodingKeys: String, CodingKey {\n        case dt, sunrise, sunset, temp\n        case feelsLike = \"feels_like\"\n        case pressure, humidity\n        case dewPoint = \"dew_point\"\n        case uvi, clouds, visibility\n        case windSpeed = \"wind_speed\"\n        case windDeg = \"wind_deg\"\n        case weather\n        case windGust = \"wind_gust\"\n        case pop, rain\n    }\n}\n\n// MARK: - OCRain\nstruct OCRain: Codable {\n    let the1H: Double?\n\n    enum CodingKeys: String, CodingKey {\n        case the1H = \"1h\"\n    }\n}\n/*\n// MARK: - OCWeather\nstruct OCWeather: Codable {\n    let id: Int?\n    let main: String?\n    let weatherDescription: String?\n    let icon: String?\n\n    enum CodingKeys: String, CodingKey {\n        case id, main\n        case weatherDescription = \"description\"\n        case icon\n    }\n}*/\n\n// MARK: - OCDaily\nstruct OCDaily: Codable {\n    let dt, sunrise, sunset: Int?\n    let temp: OCTemp?\n    let feelsLike: OCFeelsLike?\n    let pressure, humidity: Int?\n    let dewPoint, windSpeed: Double?\n    let windDeg: Int?\n    let weather: [OWWeather]?\n    let clouds: Int?\n    let pop, uvi, rain: Double?\n\n    enum CodingKeys: String, CodingKey {\n        case dt, sunrise, sunset, temp\n        case feelsLike = \"feels_like\"\n        case pressure, humidity\n        case dewPoint = \"dew_point\"\n        case windSpeed = \"wind_speed\"\n        case windDeg = \"wind_deg\"\n        case weather, clouds, pop, uvi, rain\n    }\n}\n\n// MARK: - OCFeelsLike\nstruct OCFeelsLike: Codable {\n    let day, night, eve, morn: Double?\n}\n\n// MARK: - OCTemp\nstruct OCTemp: Codable {\n    let day, min, max, night: Double?\n    let eve, morn: Double?\n}\n\n// MARK: - OCMinutely\nstruct OCMinutely: Codable {\n    let dt, precipitation: Int?\n}\n\nstruct OneCall {\n\n    static var testJson = \"\"\n\n    static func getUnits() -> String {\n        if PrefsInfo.weather.degree == .celsius {\n            return \"metric\"\n        } else {\n            return \"imperial\"\n        }\n    }\n\n    static func getShortcodeLanguage() -> String {\n        // Those are the languages supported by OpenWeather\n        let weatherLanguages = [\"af\", \"al\", \"ar\", \"az\", \"bg\", \"ca\", \"cz\", \"da\", \"de\", \"el\", \"en\",\n                                \"eu\", \"fa\", \"fi\", \"fr\", \"gl\", \"he\", \"hi\", \"hr\", \"hu\", \"id\", \"it\",\n                                \"ja\", \"kr\", \"la\", \"lt\", \"mk\", \"no\", \"nl\", \"pl\", \"pt\", \"pt_br\", \"ro\",\n                                \"ru\", \"sv\", \"sk\", \"sl\", \"es\", \"sr\", \"th\", \"tr\", \"uk\", \"vi\", \"zh_cn\",\n                                \"zh_tw\", \"zu\" ]\n\n        if PrefsAdvanced.ciOverrideLanguage == \"\" {\n            let bestMatchedLanguage = Bundle.preferredLocalizations(from: weatherLanguages, forPreferences: Locale.preferredLanguages).first\n            if let match = bestMatchedLanguage {\n                debugLog(\"Best matched language : \\(match)\")\n                return match\n            }\n        } else {\n            debugLog(\"Overrode matched language : \\(PrefsAdvanced.ciOverrideLanguage)\")\n            return PrefsAdvanced.ciOverrideLanguage\n        }\n\n        // We fallback here if nothing works\n        return \"en\"\n    }\n\n    static func makeUrl(lat: String, lon: String) -> String {\n        return \"https://api.openweathermap.org/data/2.5/onecall\"\n            + \"?lat=\\(lat)&lon=\\(lon)\"\n            + \"&units=\\(getUnits())\"\n            + \"&lang=\\(getShortcodeLanguage())\"\n            + \"&APPID=\\(APISecrets.openWeatherAppId)\"\n    }\n\n    /*\n    static func makeUrl(location: String) -> String {\n        \n        let nloc = location.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!\n\n        return \"https://api.openweathermap.org/data/2.5/onecall\"\n            + \"?q=\\(nloc)\"\n            + \"&units=\\(getUnits())\"\n            + \"&lang=\\(getShortcodeLanguage())\"\n            + \"&APPID=\\(APISecrets.openWeatherAppId)\"\n    }*/\n\n    // swiftlint:disable:next cyclomatic_complexity\n    static func fetch(completion: @escaping(Result<OCOneCall, NetworkError>) -> Void) {\n        guard testJson == \"\" else {\n            let jsonData = testJson.data(using: .utf8)!\n\n            do {\n                let openWeather = try newJSONDecoder().decode(OCOneCall.self, from: jsonData)\n                completion(.success(openWeather))\n            } catch {\n                completion(.failure(.unknown))\n            }\n\n            return\n        }\n\n        if PrefsInfo.weather.locationMode == .useCurrent {\n            let location = Locations.sharedInstance\n\n            location.getCoordinates(failure: { (_) in\n                completion(.failure(.unknown))\n            }, success: { (coordinates) in\n                let lat = String(format: \"%.2f\", coordinates.latitude)\n                let lon = String(format: \"%.2f\", coordinates.longitude)\n                debugLog(\"=== OC: Starting locationMode\")\n\n                fetchData(from: makeUrl(lat: lat, lon: lon)) { result in\n                    switch result {\n                    case .success(let jsonString):\n                        let jsonData = jsonString.data(using: .utf8)!\n\n                        if var openWeather = try? newJSONDecoder().decode(OCOneCall.self, from: jsonData) {\n                            openWeather.processTemperatures()\n\n                            completion(.success(openWeather))\n                        } else {\n                            completion(.failure(.unknown))\n                        }\n                    case .failure(_):\n                        completion(.failure(.unknown))\n                    }\n                }\n            })\n        } else {\n            // Urgh, please use location services...\n            debugLog(\"=== OC: Starting manual mode\")\n\n            GeoCoding.fetch { result in\n                switch result {\n                case .success(let geoLocation):\n                    fetchData(from: makeUrl(lat: geoLocation.lat, lon: geoLocation.lon)) { result in\n                        switch result {\n                        case .success(let jsonString):\n                            let jsonData = jsonString.data(using: .utf8)!\n\n                            if var openWeather = try? newJSONDecoder().decode(OCOneCall.self, from: jsonData) {\n                                openWeather.processTemperatures()\n\n                                completion(.success(openWeather))\n                            } else {\n                                completion(.failure(.unknown))\n                            }\n                        case .failure(_):\n                            completion(.failure(.unknown))\n                        }\n                    }\n                case .failure(let error):\n                    debugLog(error.localizedDescription)\n                    completion(.failure(.unknown))\n                }\n            }\n        }\n    }\n\n    private static func fetchData(from urlString: String, completion: @escaping (Result<String, NetworkError>) -> Void) {\n        // check the URL is OK, otherwise return with a failure\n        guard let url = URL(string: urlString) else {\n            completion(.failure(.badURL))\n            return\n        }\n\n        URLSession.shared.dataTask(with: url) { data, _, error in\n            // the task has completed – push our work back to the main thread\n            DispatchQueue.main.async {\n                if let data = data {\n                    // success: convert the data to a string and send it back\n                    let stringData = String(decoding: data, as: UTF8.self)\n                    completion(.success(stringData))\n                } else if error != nil {\n                    // any sort of network failure\n                    completion(.failure(.requestFailed))\n                } else {\n                    // this ought not to be possible, yet here we are\n                    completion(.failure(.unknown))\n                }\n            }\n        }.resume()\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Models/API/OpenWeather.swift",
    "content": "//\n//  OpenWeather.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 04/03/2021.\n//  Copyright © 2021 Guillaume Louel. All rights reserved.\n//\n// This file was generated from JSON Schema using quicktype, do not modify it directly.\n// To parse the JSON, add this file to your project and do:\n//\n//   let openWeather = try? newJSONDecoder().decode(OWeather.self, from: jsonData)\n\nimport Foundation\n\nenum NetworkError: Error {\n    case badURL\n    case requestFailed\n    case unknown\n    case cityNotFound\n}\n\n// MARK: - OpenWeather\nstruct OWeather: Codable {\n    let coord: OWCoord?\n    let weather: [OWWeather]?\n    let base: String?\n    var main: OWMain?\n    let visibility: Int?\n    let wind: OWWind?\n    let clouds: OWClouds?\n    let dt: Int?\n    let sys: OWSys?\n    let timezone, id: Int?\n    let name: String?\n    let cod: Int?\n\n    // We round them down a bit as openweather provides up to two decimal point precision\n    mutating func processTemperatures() {\n        guard main != nil else {\n            return\n        }\n\n        if PrefsInfo.weather.degree == .celsius {\n            main!.temp = main!.temp.rounded(toPlaces: 1)\n            main!.feelsLike = main!.feelsLike.rounded(toPlaces: 1)\n        } else {\n            main!.temp = main!.temp.rounded()\n            main!.feelsLike = main!.feelsLike.rounded()\n        }\n    }\n}\n\n// MARK: - OWClouds\nstruct OWClouds: Codable {\n    let all: Int?\n}\n\n// MARK: - OWCoord\nstruct OWCoord: Codable {\n    let lon, lat: Double?\n}\n// MARK: - OWMain\nstruct OWMain: Codable {\n    var temp: Double\n    var feelsLike: Double\n    var tempMin, tempMax, pressure, humidity: Double\n\n    enum CodingKeys: String, CodingKey {\n        case temp\n        case feelsLike = \"feels_like\"\n        case tempMin = \"temp_min\"\n        case tempMax = \"temp_max\"\n        case pressure, humidity\n    }\n}\n\n// MARK: - OWSys\nstruct OWSys: Codable {\n    let type, id: Int?\n    let country: String\n    let sunrise, sunset: Int\n}\n\n// MARK: - OWWeather\nstruct OWWeather: Codable {\n    let id: Int\n    let main, weatherDescription, icon: String\n\n    enum CodingKeys: String, CodingKey {\n        case id, main\n        case weatherDescription = \"description\"\n        case icon\n    }\n}\n\n// MARK: - OWWind\nstruct OWWind: Codable {\n    let speed: Double\n    let deg: Int\n    let gust: Double?\n}\n\nstruct OpenWeather {\n\n    static var testJson = \"\"\n\n    static func getUnits() -> String {\n        if PrefsInfo.weather.degree == .celsius {\n            return \"metric\"\n        } else {\n            return \"imperial\"\n        }\n    }\n\n    static func getShortcodeLanguage() -> String {\n        // Those are the languages supported by OpenWeather\n        let weatherLanguages = [\"af\", \"al\", \"ar\", \"az\", \"bg\", \"ca\", \"cz\", \"da\", \"de\", \"el\", \"en\",\n                                \"eu\", \"fa\", \"fi\", \"fr\", \"gl\", \"he\", \"hi\", \"hr\", \"hu\", \"id\", \"it\",\n                                \"ja\", \"kr\", \"la\", \"lt\", \"mk\", \"no\", \"nl\", \"pl\", \"pt\", \"pt_br\", \"ro\",\n                                \"ru\", \"sv\", \"sk\", \"sl\", \"es\", \"sr\", \"th\", \"tr\", \"uk\", \"vi\", \"zh_cn\",\n                                \"zh_tw\", \"zu\" ]\n\n        if PrefsAdvanced.ciOverrideLanguage == \"\" {\n            let bestMatchedLanguage = Bundle.preferredLocalizations(from: weatherLanguages, forPreferences: Locale.preferredLanguages).first\n            if let match = bestMatchedLanguage {\n                debugLog(\"Best matched language : \\(match)\")\n                return match\n            }\n        } else {\n            debugLog(\"Overrode matched language : \\(PrefsAdvanced.ciOverrideLanguage)\")\n            return PrefsAdvanced.ciOverrideLanguage\n        }\n\n        // We fallback here if nothing works\n        return \"en\"\n    }\n\n    static func makeUrl(lat: String, lon: String) -> String {\n        return \"https://api.openweathermap.org/data/2.5/weather\"\n            + \"?lat=\\(lat)&lon=\\(lon)\"\n            + \"&units=\\(getUnits())\"\n            + \"&lang=\\(getShortcodeLanguage())\"\n            + \"&APPID=\\(APISecrets.openWeatherAppId)\"\n    }\n\n    static func makeUrl(location: String) -> String {\n        let nloc = location.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!\n\n        return \"https://api.openweathermap.org/data/2.5/weather\"\n            + \"?q=\\(nloc)\"\n            + \"&units=\\(getUnits())\"\n            + \"&lang=\\(getShortcodeLanguage())\"\n            + \"&APPID=\\(APISecrets.openWeatherAppId)\"\n    }\n\n    static func fetch(completion: @escaping(Result<OWeather, NetworkError>) -> Void) {\n        guard testJson == \"\" else {\n            let jsonData = testJson.data(using: .utf8)!\n\n            if var openWeather = try? newJSONDecoder().decode(OWeather.self, from: jsonData) {\n                openWeather.processTemperatures()\n\n                completion(.success(openWeather))\n            } else {\n                completion(.failure(.cityNotFound))\n            }\n\n            return\n        }\n\n        if PrefsInfo.weather.locationMode == .useCurrent {\n            let location = Locations.sharedInstance\n\n            location.getCoordinates(failure: { (_) in\n                completion(.failure(.unknown))\n            }, success: { (coordinates) in\n                let lat = String(format: \"%.2f\", coordinates.latitude)\n                let lon = String(format: \"%.2f\", coordinates.longitude)\n                debugLog(\"=== OW: Starting locationMode\")\n\n                fetchData(from: makeUrl(lat: lat, lon: lon)) { result in\n                    switch result {\n                    case .success(let jsonString):\n                        \n\n                        let jsonData = jsonString.data(using: .utf8)!\n\n                        do {\n                            var openWeather = try newJSONDecoder().decode(OWeather.self, from: jsonData)\n                            openWeather.processTemperatures()\n                            completion(.success(openWeather))\n                        } catch {\n                            debugLog(\"=== OW: JSON decoding failed: \\(error)\")\n                            if let decodingError = error as? DecodingError {\n                                switch decodingError {\n                                case .keyNotFound(let key, let context):\n                                    debugLog(\"=== OW: Missing key '\\(key.stringValue)' at: \\(context.codingPath.map { $0.stringValue }.joined(separator: \".\"))\")\n                                case .typeMismatch(let type, let context):\n                                    debugLog(\"=== OW: Type mismatch for \\(type) at: \\(context.codingPath.map { $0.stringValue }.joined(separator: \".\"))\")\n                                case .valueNotFound(let type, let context):\n                                    debugLog(\"=== OW: Missing value for \\(type) at: \\(context.codingPath.map { $0.stringValue }.joined(separator: \".\"))\")\n                                case .dataCorrupted(let context):\n                                    debugLog(\"=== OW: Data corrupted at: \\(context.codingPath.map { $0.stringValue }.joined(separator: \".\"))\")\n                                @unknown default:\n                                    debugLog(\"=== OW: Unknown decoding error\")\n                                }\n                            }\n                            completion(.failure(.cityNotFound))\n                        }\n                    case .failure(let error):\n                        completion(.failure(.unknown))\n                    }\n                }\n            })\n        } else {\n            // Just in case, we add a failsafe\n            if PrefsInfo.weather.locationString == \"\" {\n                PrefsInfo.weather.locationString = \"Paris, FR\"\n            }\n            debugLog(\"=== OW: Starting manual mode\")\n\n            fetchData(from: makeUrl(location: PrefsInfo.weather.locationString)) { result in\n                switch result {\n                case .success(let jsonString):\n                    let jsonData = jsonString.data(using: .utf8)!\n                    do {\n                        var openWeather = try newJSONDecoder().decode(OWeather.self, from: jsonData)\n                        openWeather.processTemperatures()\n                        completion(.success(openWeather))\n                    } catch {\n                        debugLog(\"=== OW: JSON decoding failed: \\(error)\")\n                        if let decodingError = error as? DecodingError {\n                            switch decodingError {\n                            case .keyNotFound(let key, let context):\n                                debugLog(\"=== OW: Missing key '\\(key.stringValue)' at: \\(context.codingPath.map { $0.stringValue }.joined(separator: \".\"))\")\n                            case .typeMismatch(let type, let context):\n                                debugLog(\"=== OW: Type mismatch for \\(type) at: \\(context.codingPath.map { $0.stringValue }.joined(separator: \".\"))\")\n                            case .valueNotFound(let type, let context):\n                                debugLog(\"=== OW: Missing value for \\(type) at: \\(context.codingPath.map { $0.stringValue }.joined(separator: \".\"))\")\n                            case .dataCorrupted(let context):\n                                debugLog(\"=== OW: Data corrupted at: \\(context.codingPath.map { $0.stringValue }.joined(separator: \".\"))\")\n                            @unknown default:\n                                debugLog(\"=== OW: Unknown decoding error\")\n                            }\n                        }\n                        completion(.failure(.cityNotFound))\n                    }\n                case .failure(_):\n                    completion(.failure(.unknown))\n                }\n            }\n\n        }\n    }\n\n    private static func fetchData(from urlString: String, completion: @escaping (Result<String, NetworkError>) -> Void) {\n        // check the URL is OK, otherwise return with a failure\n        guard let url = URL(string: urlString) else {\n            completion(.failure(.badURL))\n            return\n        }\n\n        URLSession.shared.dataTask(with: url) { data, _, error in\n            // the task has completed – push our work back to the main thread\n            DispatchQueue.main.async {\n                if let data = data {\n                    // success: convert the data to a string and send it back\n                    let stringData = String(decoding: data, as: UTF8.self)\n                    completion(.success(stringData))\n                } else if error != nil {\n                    // any sort of network failure\n                    completion(.failure(.requestFailed))\n                } else {\n                    // this ought not to be possible, yet here we are\n                    completion(.failure(.unknown))\n                }\n            }\n        }.resume()\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Models/Aerial.swift",
    "content": "//\n//  Aerial.swift\n//  Aerial\n//\n//  Contains some common helpers used throughout the code\n//\n//  Created by Guillaume Louel on 17/07/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Cocoa\n\nclass Aerial: NSObject {\n    static let helper = Aerial()\n    \n    var windowController: PanelWindowController?\n\n    // We use this to track whether we run as a screen saver or an app\n    var appMode = false\n\n    // We also track darkmode here now\n    var darkMode = false\n\n    // And we track if we are running under Aerial's Companion \n    var underCompanion = false\n\n    let userName = NSUserName()\n    \n    // Track our version number for logs and stuff\n    var version: String = {\n        if let version = Bundle(identifier: \"com.johncoates.Aerial-Test\")?.infoDictionary?[\"CFBundleShortVersionString\"] as? String {\n            return \"Version \" + version\n        } else if let version = Bundle(identifier: \"com.JohnCoates.Aerial\")?.infoDictionary?[\"CFBundleShortVersionString\"] as? String {\n            return \"Version \" + version\n        }\n\n        return \"Version ?\"\n    }()\n\n\n    // Using HDR in the panel will crash System Settings in macOS 13. This is fixed in macOS 13.4 🎉\n    func canHDR() -> Bool {\n        if #available(OSX 13.0, *) {\n            if #unavailable(OSX 13.4) {\n                return false\n            }\n        }\n        \n        return true\n    }\n    \n    // Are we running under Aerial Companion ? Desktop mode/Fullscreen mode\n    // Xcode debug mode is also considered as running under Companion\n    \n    func checkCompanion() {\n        logToConsole(\"Checking for companion\")\n        if appMode {\n            underCompanion = true\n            logToConsole(\"> Running in appMode, simming Companion!\")\n        } else {\n            for bundle in Bundle.allBundles {\n                if let bundleId = bundle.bundleIdentifier {\n                    if bundleId.contains(\"AerialUpdater\") {\n                        underCompanion = true\n                        logToConsole(\"> Running under Aerial Companion!\")\n                    }\n                }\n            }\n        }\n    }\n\n    func computeDarkMode(view: NSView) {\n        if #available(OSX 10.14, *) {\n            //debugLog(\"Best match appearance : \\(view.effectiveAppearance.bestMatch(from: [.darkAqua, .aqua]))\")\n            //debugLog(\"Effective Appearence : \\(view.effectiveAppearance)\")\n            darkMode =  view.effectiveAppearance.bestMatch(from: [.darkAqua, .aqua]) == .darkAqua\n        } else {\n            darkMode = false\n        }\n    }\n\n    // Language detection\n    func getPreferredLanguage() -> String {\n        let printOutputLocale: NSLocale = NSLocale(localeIdentifier: Locale.preferredLanguages[0])\n        if let deviceLanguageName: String = printOutputLocale.displayName(forKey: .identifier, value: Locale.preferredLanguages[0]) {\n            if #available(OSX 10.12, *) {\n                return \"Preferred language: \\(deviceLanguageName) [\\(printOutputLocale.languageCode)]\"\n            } else {\n                return \"Preferred language: \\(deviceLanguageName)\"\n            }\n        } else {\n            return \"\"\n        }\n    }\n\n    // Alerts\n    func showErrorAlert(question: String, text: String, button: String = \"OK\") {\n        let alert = NSAlert()\n        alert.messageText = question\n        alert.informativeText = text\n        alert.alertStyle = .critical\n        alert.icon = NSImage(named: NSImage.cautionName)\n        alert.addButton(withTitle: button)\n        alert.runModal()\n    }\n\n    func showAlert(question: String, text: String, button1: String = \"OK\", button2: String = \"Cancel\") -> Bool {\n        let alert = NSAlert()\n        alert.messageText = question\n        alert.informativeText = text\n        alert.alertStyle = .warning\n        alert.icon = NSImage(named: NSImage.cautionName)\n        alert.addButton(withTitle: button1)\n        alert.addButton(withTitle: button2)\n        return alert.runModal() == NSApplication.ModalResponse.alertFirstButtonReturn\n    }\n\n    func showInfoAlert(title: String, text: String, button1: String = \"OK\", caution: Bool = false) {\n        let alert = NSAlert()\n        alert.messageText = title\n        alert.informativeText = text\n        alert.alertStyle = .warning\n        if caution {\n            alert.icon = NSImage(named: NSImage.cautionName)\n        } else {\n            alert.icon = NSImage(named: NSImage.infoName)\n        }\n        alert.addButton(withTitle: button1)\n        alert.runModal()\n    }\n\n    // Symbol/icon generation\n\n    // Symbol as a CALayer\n    func getSymbolLayer(_ named: String, size: CGFloat) -> CALayer {\n        let imglayer = CALayer()\n        imglayer.contents = Aerial.helper.getSymbol(named)\n        imglayer.frame.size = CGSize(width: size,\n                                     height: size)\n        return imglayer\n    }\n\n    // Symbol as a NSImage\n    func getSymbol(_ named: String) -> NSImage? {\n        // Use SFSymbols if available\n        if #available(macOS 11.0, *) {\n            if let image = NSImage(systemSymbolName: named, accessibilityDescription: named) {\n                image.isTemplate = true\n\n                // return image\n                let config = NSImage.SymbolConfiguration(pointSize: 100, weight: .regular)\n                return image.withSymbolConfiguration(config)?.tinting(with: .white)\n            }\n        }\n\n        if let imagePath = Bundle(for: PanelWindowController.self).path(\n            forResource: fallbackSymbol(named),\n            ofType: \"pdf\") {\n            return NSImage(contentsOfFile: imagePath)\n        }\n\n        return nil\n    }\n\n    func getMiniSymbol(_ named: String, tint: NSColor = .labelColor) -> NSImage? {\n        if let symbol = getSymbol(named) {\n            return resize(image: symbol, w: Int(symbol.size.width)/10, h: Int(symbol.size.height)/10).tinting(with: tint)\n        } else {\n            return nil\n        }\n    }\n\n    // TODO: move to extension of NSImage...\n    // swiftlint:disable:next identifier_name\n    func resize(image: NSImage, w: Int, h: Int) -> NSImage {\n        let destSize = NSSize(width: CGFloat(w), height: CGFloat(h))\n        let newImage = NSImage(size: destSize)\n        newImage.lockFocus()\n        image.draw(in: NSRect(x: 0, y: 0,\n                              width: destSize.width,\n                              height: destSize.height),\n                   from: NSRect(x: 0, y: 0, width: image.size.width, height: image.size.height),\n                   operation: NSCompositingOperation.sourceOver, fraction: CGFloat(1))\n        newImage.unlockFocus()\n        newImage.size = destSize\n        return NSImage(data: newImage.tiffRepresentation!)!\n    }\n\n    func getAccentedSymbol(_ named: String) -> NSImage? {\n        if #available(OSX 10.14, *) {\n            return getSymbol(named)?.tinting(with: .controlAccentColor)\n        } else {\n            // Fallback on earlier versions\n            return getSymbol(named)?.tinting(with: .systemBlue)\n        }\n    }\n\n    // This is a list of fallback symbols, until we can use those from SF Symbols 2,\n    // we export from SF Symbols 1...\n    private func fallbackSymbol(_ forName: String) -> String {\n        switch forName {\n        case \"cloud\":\n            return \"regular.cloud\"\n        case \"sun.max\":\n            return \"regular.sun.max\"\n        case \"sun.min\":\n            return \"regular.sun.min\"\n        case \"moon.stars\":\n            return \"regular.moon.stars\"\n        case \"leaf\":\n            return \"flame\"\n        case \"dial.min\":\n            return \"dial\"\n        case \"internaldrive\":\n            return \"arrow.down.circle\"\n        case \"display.2\":\n            return \"tv\"\n        case \"wrench.and.screwdriver\":\n            return \"wrench\"\n        default:\n            return forName\n        }\n\n    }\n\n    // Launch a process through shell and capture/return output\n    func shell(launchPath: String, arguments: [String] = []) -> (String?, Int32) {\n        let task = Process()\n        task.launchPath = launchPath\n        task.arguments = arguments\n\n        let pipe = Pipe()\n        task.standardOutput = pipe\n        task.standardError = pipe\n\n        if #available(OSX 10.13, *) {\n            do {\n                try task.run()\n            } catch {\n                // handle errors\n                debugLog(\"Error: \\(error.localizedDescription)\")\n            }\n        } else {\n            // A non existing command will crash 10.12\n            task.launch()\n        }\n\n        let data = pipe.fileHandleForReading.readDataToEndOfFile()\n        let output = String(data: data, encoding: .utf8)\n        task.waitUntilExit()\n\n        return (output, task.terminationStatus)\n    }\n\n    func shell(_ command:String, args: [String] = []) -> String\n    {\n        let task = Process()\n        var arguments = [\"-c\"]\n        arguments.append(command)\n        arguments += args\n        task.launchPath = \"/bin/bash\"\n        task.arguments = arguments\n        \n        let pipe = Pipe()\n        task.standardOutput = pipe\n        task.launch()\n        \n        \n        let data = pipe.fileHandleForReading.readDataToEndOfFile()\n        let output = String(data: data, encoding: .utf8)\n        task.waitUntilExit()\n\n        return output ?? \"\"\n        \n/*        let data = pipe.fileHandleForReading.readDataToEndOfFile()\n        let output = String(data: data, encoding: String.Encoding.utf8)!\n*/        /*if output.count > 0 {\n            //remove newline character.\n            let lastIndex = output.index(before: output.endIndex)\n            return String(output[output.startIndex ..< lastIndex])\n        }*/\n        //return output\n    }\n    \n    // Launch a process through shell and capture/return output\n    func shell(executableURL: String, arguments: [String] = []) -> (String?, Int32) {\n        let task = Process()\n        task.executableURL = URL(fileURLWithPath: executableURL)\n        task.arguments = arguments\n\n        let pipe = Pipe()\n        task.standardOutput = pipe\n        task.standardError = pipe\n\n        if #available(OSX 10.13, *) {\n            do {\n                try task.run()\n            } catch {\n                // handle errors\n                debugLog(\"Error: \\(error.localizedDescription)\")\n            }\n        } else {\n            // A non existing command will crash 10.12\n            task.launch()\n        }\n\n        let data = pipe.fileHandleForReading.readDataToEndOfFile()\n        let output = String(data: data, encoding: .utf8)\n        task.waitUntilExit()\n\n        return (output, task.terminationStatus)\n    }\n\n    \n    /*\n    func trySettings() {\n        let date = Date()\n        let dateFormatter = DateFormatter()\n        dateFormatter.timeStyle = .long\n        dateFormatter.dateStyle = .none\n        let time = dateFormatter.string(from: date)\n        let bundleID = \"/Users/guillaume/Library/Containers/com.apple.ScreenSaver.Engine.legacyScreenSaver/Data/Library/Preferences/com.glouel.synctest\"\n\n        // Test 1\n        CFPreferencesSetValue(\"underCompanion\" as CFString, (underCompanion ? \"under\" : \"notunder\") as CFString, bundleID as CFString as CFString, kCFPreferencesCurrentUser, kCFPreferencesAnyHost)\n\n        CFPreferencesSetValue(\"lastRun\" as CFString, time as CFString, bundleID as CFString as CFString, kCFPreferencesCurrentUser, kCFPreferencesAnyHost)\n\n        let val = CFPreferencesAppSynchronize(bundleID as CFString)\n        print(\"value : \" + String(val))\n        \n        \n        // Test 2\n        let bundleID2 = \"/Users/guillaume/Library/Containers/com.apple.ScreenSaver.Engine.legacyScreenSaver/Data/Library/Preferences/com.glouel.synctest2\"\n        let userDefaults = UserDefaults(suiteName: bundleID2)\n        userDefaults?.setValue(time, forKey: \"lastRun\")\n\n        userDefaults?.synchronize()\n\n\n        userDefaults?.setValue(underCompanion ? \"under\" : \"notunder\", forKey: \"underCompanion\")\n        userDefaults?.setValue(time, forKey: \"lastRun\")\n\n        userDefaults?.synchronize()\n        \n \n        /*let (result, _) = shell(launchPath: \"/usr/bin/defaults\", arguments: [\"read\", \"~/Library/Preferences/com.glouel.synctest\",\"lastRun\"])\n        debugLog(result!)\n        print(result!)*/\n    }*/\n    \n    func getPreferencesDirectory() -> String {\n        // Grab an array of Application Support paths\n        let libPaths = NSSearchPathForDirectoriesInDomains(\n            .libraryDirectory,\n            .userDomainMask,\n            true)\n        \n        if !libPaths.isEmpty {\n            if underCompanion {\n                return libPaths.first! + \"/Containers/com.apple.ScreenSaver.Engine.legacyScreenSaver/Data/Library/Preferences/\"\n                \n            } else {\n                return libPaths.first! + \"/Preferences/\"\n            }\n        } else {\n            return \"/Users/\" + Aerial.helper.userName + \"/Library/Containers/com.apple.ScreenSaver.Engine.legacyScreenSaver/Data/Library/Preferences/\"\n        }\n    }\n    \n    \n    // Starting with 3.1.0beta2, existing settings are moved from Preferences/ByHost to Preferences\n    // This allows the sharing of preferences between regular screen saver and companion-hosted screensaver\n    func migratePreferences() {\n        // First check if the new settings already exists !\n        let baseContainerPrefPath = getPreferencesDirectory()\n        \n        let newBundleFile = baseContainerPrefPath + \"com.glouel.Aerial.plist\"\n\n        if FileManager.default.fileExists(atPath: newBundleFile) {\n            // We are done\n            logToConsole(\"!!! New prefs already exists\")\n        } else {\n            logToConsole(\"!!! New prefs does NOT exist\")\n            //Look for ByHost\n            let byHostPath = baseContainerPrefPath + \"ByHost/\"\n            \n            if FileManager.default.fileExists(atPath: byHostPath) {\n                logToConsole(\"ByHost exists\")\n                var oldPlist = \"\"\n                \n                // Try and find the old plist\n                do {\n                    let directoryContents = try FileManager.default.contentsOfDirectory(atPath: byHostPath)\n\n                    for directoryContent in directoryContents {\n                        if directoryContent.starts(with: \"com.JohnCoates.Aerial\") {\n                            // We found it !\n                            oldPlist = directoryContent\n                            break\n                        }\n                    }\n                } catch {\n                    logToConsole(error.localizedDescription)\n                }\n\n                // Did we get it ?\n                if oldPlist != \"\" {\n                    logToConsole(\"plist found \" + oldPlist)\n                    do {\n                        try FileManager.default.copyItem(atPath: byHostPath + oldPlist, toPath: newBundleFile)\n                        logToConsole(\"plist moved\")\n                    } catch {\n                        logToConsole(error.localizedDescription)\n                    }\n                }\n            }\n        }\n    }\n    \n    // Mute me maybe\n    func maybeMuteSound() {\n        if !appMode && !underCompanion && PrefsAdvanced.muteGlobalSound{\n            Sound.output.isMuted = true\n        }\n    }\n    \n    func maybeUnmuteSound() {\n        if !appMode && !underCompanion && PrefsAdvanced.muteGlobalSound {\n            Sound.output.isMuted = false\n        }\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Models/AerialVideo.swift",
    "content": "//\n//  AerialVideo.swift\n//  Aerial\n//\n//  Created by John Coates on 10/23/15.\n//  Copyright © 2015 John Coates. All rights reserved.\n//\n\nimport Cocoa\nimport AVFoundation\n\nenum Manifests: String {\n    case tvOS10 = \"tvos10.json\", tvOS11 = \"tvos11.json\", tvOS12 = \"tvos12.json\", tvOS13 = \"tvos13.json\", tvOS13Strings = \"TVIdleScreenStrings13.bundle\", customVideos = \"customvideos.json\"\n}\n\nfinal class AerialVideo: CustomStringConvertible, Equatable {\n    static func ==(lhs: AerialVideo, rhs: AerialVideo) -> Bool {\n        return lhs.id == rhs.id // TODO && lhs.url1080pHEVC == rhs.url1080pHEVC\n    }\n\n    let id: String\n    let name: String\n    let secondaryName: String\n    let type: String\n    let timeOfDay: String\n    let scene: SourceScene\n\n    var urls: [VideoFormat: String]\n\n    let source: Source\n    // var sources: [Manifests]\n    let poi: [String: String]\n    let communityPoi: [String: String]\n    var duration: Double\n\n    var arrayPosition = 1\n    var contentLength = 0\n    var contentLengthChecked = false\n\n    var isVertical: Bool\n\n    var isAvailableOffline: Bool {\n        return VideoCache.isAvailableOffline(video: self)\n    }\n\n    // MARK: - Public getter\n    var url: URL {\n        return getClosestAvailable(wanted: PrefsVideos.videoFormat)\n    }\n\n    // Returns the closest video we have in the manifests\n    private func getClosestAvailable(wanted: VideoFormat) -> URL {\n        if urls[wanted] != \"\" && urls[wanted] != nil {\n            return getURL(string: urls[wanted]!)\n        } else {\n            // Fallback\n            if urls.keys.contains(.v4KHEVC), urls[.v4KHEVC] != \"\" {\n                return getURL(string: urls[.v4KHEVC]!)\n            } else if urls.keys.contains(.v4KSDR240), urls[.v4KSDR240] != \"\" {\n                // macOS manifest only have those\n                return getURL(string: urls[.v4KSDR240]!)\n            } else if urls.keys.contains(.v1080pHEVC), urls[.v1080pHEVC] != \"\" {\n                return getURL(string: urls[.v1080pHEVC]!)\n            } else if urls.keys.contains(.v1080pH264), urls[.v1080pH264] != \"\" { // Last resort\n                return getURL(string: urls[.v1080pH264]!)\n            } else {\n                errorLog(\"getClosestAvailable failed back hard to 4KHDR\")\n                // Something went very wrong if we are here\n                return getURL(string: urls[.v4KHDR]!)\n            }\n        }\n    }\n    private func getURL(string: String) -> URL {\n        if string.starts(with: \"/\") {\n            return URL(fileURLWithPath: string)\n        } else {\n            return URL(string: string)!\n        }\n    }\n\n    // swiftlint:disable cyclomatic_complexity\n    // MARK: - Init\n    init(id: String,\n         name: String,\n         secondaryName: String,\n         type: String,\n         timeOfDay: String,\n         scene: String,\n         urls: [VideoFormat: String],\n         source: Source,\n         poi: [String: String],\n         communityPoi: [String: String]\n    ) {\n        self.id = id\n\n        // We override names for known space videos\n        if SourceInfo.seaVideos.contains(id) {\n            self.name = \"Sea\"\n            if secondaryName != \"\" {\n                self.secondaryName = secondaryName\n            } else {\n                self.secondaryName = name\n            }\n        } else if SourceInfo.spaceVideos.contains(id) {\n            self.name = \"Space\"\n            if secondaryName != \"\" {\n                self.secondaryName = secondaryName\n            } else {\n                self.secondaryName = name\n            }\n        } else {\n            // We align to the new jsons...\n            if name == \"New York City\" {\n                self.name = \"New York\"\n            } else {\n                self.name = name\n            }\n            self.secondaryName = secondaryName      // We may have a secondary name from our merges too now !\n        }\n\n        self.type = type\n\n        // We override timeOfDay based on our own list\n        if let val = SourceInfo.timeInformation[id] {\n            self.timeOfDay = val\n        } else {\n            self.timeOfDay = timeOfDay\n        }\n\n        switch scene {\n        case \"sea\":\n            self.scene = .sea\n        case \"space\":\n            self.scene = .space\n        case \"city\":\n            self.scene = .city\n        case \"countryside\":\n            self.scene = .countryside\n        case \"beach\":\n            self.scene = .beach\n        default:\n            self.scene = .nature\n        }\n\n        self.urls = urls\n        self.source = source\n        // self.sources = [manifest]\n        self.poi = poi\n        self.communityPoi = communityPoi\n\n        // Default stuff, we double check those below\n        self.duration = 0\n        self.isVertical = false\n\n        updateDuration()    // We need to have the video duration\n    }\n\n\n\n    \n    func updateDuration() {\n        // We need to retrieve video duration from the cached files.\n        // This is a workaround as currently, the VideoCache infrastructure\n        // relies on AVAsset with an external URL all the time, even when\n        // working on a cached copy which makes the native duration retrieval fail\n        //\n        // And... we also check the orientation now too ;)\n\n        let fileManager = FileManager.default\n\n        if let duration = PrefsVideos.durationCache[self.id] {\n            // debugLog(\"Using cache duration : \\(duration)\")\n            self.duration = duration\n            return\n        }\n\n        // With custom videos, we may already store the local path\n        // If so, check it\n        if self.url.absoluteString.starts(with: \"file\") {\n            if fileManager.fileExists(atPath: self.url.path) {\n                let asset = AVAsset(url: self.url)\n                self.duration = CMTimeGetSeconds(asset.duration)\n                self.isVertical = asset.isVertical()\n            } else {\n                errorLog(\"Custom video is missing : \\(self.url.path)\")\n                self.duration = 0\n            }\n        } else {\n            // If not, iterate through all possible versions to see if any is cached\n            for format in VideoFormat.allCases {\n                // swiftlint:disable:next for_where\n                if urls[format] != \"\" {\n\n                    let path = VideoList.instance.localPathFor(video: self)\n\n                    if fileManager.fileExists(atPath: path) {\n                        let asset = AVAsset(url: URL(fileURLWithPath: path))\n                        self.duration = CMTimeGetSeconds(asset.duration)\n\n                        // debugLog(\"Caching video duration\")\n                        PrefsVideos.durationCache[self.id] = self.duration\n\n                        return\n                    }\n                }\n            }\n        }\n    }\n\n    /// Check if a video has HDR files or not\n    func hasHDR() -> Bool {\n        if urls[.v1080pHDR] != \"\" || urls[.v4KHDR] != \"\" {\n            return true\n        } else {\n            return false\n        }\n\n    }\n\n    /// Check if what we are playing is HDR or not\n    func isHDR() -> Bool {\n        if urls[.v1080pHDR] != \"\" {\n            if url == URL(string: urls[.v1080pHDR]!) {\n                return true\n            }\n        }\n\n        if urls[.v4KHDR] != \"\" {\n            if url == URL(string: urls[.v4KHDR]!) {\n                return true\n            }\n        }\n\n        return false\n    }\n\n    func getCurrentFormat() -> String {\n        let wanted = PrefsVideos.videoFormat\n        if urls[wanted] != \"\" {\n            switch wanted {\n            case .v4KHDR:\n                return \"4K HDR\"\n            case .v1080pH264:\n                return \"1080p\"\n            case .v1080pHEVC:\n                return \"1080p\"\n            case .v1080pHDR:\n                return \"1080p HDR\"\n            case .v4KHEVC:\n                return \"4K\"\n            case .v4KSDR240:\n                return \"4K 240FPS\"\n            }\n        } else {\n            return getBestFormat()\n        }\n    }\n\n    private func getBestFormat() -> String {\n        if urls[.v4KHDR] != \"\" {\n            return \"4K HDR\"\n        } else if urls[.v4KHEVC] != \"\" {\n            return \"4K\"\n        } else {\n            return \"1080p\"\n        }\n    }\n\n    var description: String {\n        return \"\"\"\n        id=\\(id),\n        name=\\(name),\n        type=\\(type),\n        timeofDay=\\(timeOfDay),\n        urls=\\(urls)\n        \"\"\"\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Models/Cache/AssetLoaderDelegate.swift",
    "content": "//\n//  AssetLoaderDelegate.swift\n//  Aerial\n//\n\n// This class adapted from https://github.com/renjithn/AVAssetResourceLoader-Video-Example\n\nimport Foundation\nimport AVKit\nimport AVFoundation\n\n/// Returns an AVURLAsset that is automatically cached. If already cached\n/// then returns the cached asset.\nfunc cachedOrCachingAsset(_ URL: Foundation.URL) -> AVURLAsset {\n    let assetLoader = AssetLoaderDelegate(URL: URL)\n    let asset = AVURLAsset(url: assetLoader.URLWithCustomScheme)\n    let queue = DispatchQueue.main\n    asset.resourceLoader.setDelegate(assetLoader, queue: queue)\n    objc_setAssociatedObject(asset, \"assetLoader\", assetLoader, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)\n    // debugLog(\"\\(asset)\")\n    return asset\n}\n\nfinal class AssetLoaderDelegate: NSObject, AVAssetResourceLoaderDelegate, VideoLoaderDelegate {\n\n    let URL: Foundation.URL\n    var videoLoaders: [VideoLoader] = []\n    let videoCache: VideoCache\n\n    var URLWithCustomScheme: Foundation.URL {\n        var components = URLComponents(url: URL, resolvingAgainstBaseURL: false)!\n        components.scheme = \"streaming\"\n        return components.url!\n    }\n\n    init(URL: Foundation.URL) {\n        self.URL = URL\n        videoCache = VideoCache(URL: URL)\n    }\n\n    deinit {\n        debugLog(\"AssetLoaderDelegate deinit\")\n    }\n\n    // MARK: - Video Loader Delegate\n\n    func videoLoader(_ videoLoader: VideoLoader, receivedResponse response: URLResponse) {\n        videoCache.receivedContentLength(Int(response.expectedContentLength))\n    }\n\n    func videoLoader(_ videoLoader: VideoLoader, receivedData data: Data, forRange range: NSRange) {\n        videoCache.receivedData(data, atRange: range)\n    }\n\n    // MARK: - Asset Resource Loader Delegate\n    func resourceLoader(_ resourceLoader: AVAssetResourceLoader,\n                        didCancel loadingRequest: AVAssetResourceLoadingRequest) {\n//        debugLog(\"cancelled load request: \\(loadingRequest)\")\n\n        var remove: VideoLoader?\n        for loader in videoLoaders {\n            if loader.loadingRequest != loadingRequest {\n                continue\n            }\n\n            if let connection = loader.connection {\n                connection.cancel()\n            }\n\n            remove = loader\n            break\n        }\n\n        if let removeLoader = remove {\n            if let index = videoLoaders.firstIndex(of: removeLoader) {\n                videoLoaders.remove(at: index)\n            }\n        }\n    }\n\n    func resourceLoader(_ resourceLoader: AVAssetResourceLoader,\n                        shouldWaitForLoadingOfRequestedResource\n        loadingRequest: AVAssetResourceLoadingRequest) -> Bool {\n\n        // check if cache can fulfill this without a request\n        if videoCache.canFulfillLoadingRequest(loadingRequest) {\n            if videoCache.fulfillLoadingRequest(loadingRequest) {\n                // debugLog(\"fullfilling loading request\")\n                return true\n            }\n        }\n\n        // assign request to VideoLoader\n        // debugLog(\"request to loader \\(loadingRequest)\")\n        let videoLoader = VideoLoader(url: URL, loadingRequest: loadingRequest, delegate: self)\n        videoLoaders.append(videoLoader)\n\n        return true\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Models/Cache/Cache.swift",
    "content": "//\n//  Cache.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 06/06/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Cocoa\nimport CoreWLAN\nimport AVKit\n\n/**\n Aerial's new Cache management\n \n Everything Cache related is moved here.\n \n - Note: Where is our cache ?\n \n Starting with 2.0, Aerial is putting its files in two locations :\n - `~/Library/Application Support/Aerial/` : Contains manifests files and strings bundles for each source, in their own directory\n - `~/Library/Application Support/Aerial/Cache/` : Contains (only) the cached videos\n \n Users of version 1.x.x will automatically see their video files migrated to the correct location.\n \n In Catalina, those paths live inside a user's container :\n `~/Library/Containers/com.apple.ScreenSaver.Engine.legacyScreenSaver/Data/Library/Application Support/`\n \n - Attention: Shared by multiple users writable locations are no longer possible, because sandboxing is awesome !\n */\n\n// swiftlint:disable:next type_body_length\nstruct Cache {\n    /**\n     Returns the SSID of the Wi-Fi network the user is currently connected to.\n     - Note: Returns an empty string if not connected to Wi-Fi\n     */\n    static var ssid: String {\n        return CWWiFiClient.shared().interface(withName: nil)?.ssid() ?? \"\"\n    }\n\n    static var processedSupportPath = \"\"\n\n    /**\n     Returns Aerial's Application Support path.\n     \n     + On macOS 10.14 and earlier : `~/Library/Application Support/Aerial/`\n     + Starting with 10.15 : `~/Library/Containers/com.apple.ScreenSaver.Engine.legacyScreenSaver/Data/Library/Application Support/Aerial/`\n     \n     - Note: Returns `/` on failure.\n     \n     In some rare instances those system folders may not exist in the container, in this case Aerial can't work.\n     */\n    static var supportPath: String {\n        // Dont' redo the thing all the time\n        if processedSupportPath != \"\" {\n            return processedSupportPath\n        }\n\n        var appPath = \"\"\n\n        if PrefsCache.overrideCache {\n            debugLog(\"Cache Override\")\n            if !Aerial.helper.underCompanion, #available(macOS 12, *) {\n                if let bookmarkData = PrefsCache.supportBookmarkData {\n                    do {\n                        var isStale = false\n                        let bookmarkUrl = try URL(resolvingBookmarkData: bookmarkData, options: .withSecurityScope, relativeTo: nil, bookmarkDataIsStale: &isStale)\n\n                        //debugLog(\"Bookmark is stale : \\(isStale)\")\n                        appPath = bookmarkUrl.path\n\n                        do {\n                            let url = try NSURL.init(resolvingBookmarkData: bookmarkData, options: .withoutUI, relativeTo: nil, bookmarkDataIsStale: nil)\n\n                            url.startAccessingSecurityScopedResource()\n                        } catch let error as NSError {\n                            errorLog(\"Bookmark Access Failed: \\(error.description)\")\n                        }\n                    } catch let error {\n                        errorLog(\"Can't process bookmark \\(error)\")\n                    }\n                } else {\n                    errorLog(\"Can't find supportBookmarkData on macOS 12\")\n                }\n            } else {\n                if let customPath = PrefsCache.supportPath {\n                    debugLog(\"Trying \\(customPath)\")\n                    if FileManager.default.fileExists(atPath: customPath) {\n                        appPath = customPath\n                    } else {\n                        errorLog(\"Could not find your custom Caches path, reverting to default settings\")\n                    }\n                } else {\n                    errorLog(\"Empty path, reverting to default settings\")\n                }\n            }\n        }\n\n        // This is the normal(ish) path\n        if appPath == \"\" {\n            // This is the normal path via screensaver\n            if !Aerial.helper.underCompanion {\n                // Grab an array of Application Support paths\n                let appSupportPaths = NSSearchPathForDirectoriesInDomains(\n                    .applicationSupportDirectory,\n                    .userDomainMask,\n                    true)\n\n                if appSupportPaths.isEmpty {\n                    errorLog(\"FATAL : app support does not exist!\")\n                    return \"/\"\n                }\n\n                appPath = appSupportPaths[0]\n            } else {\n                // If we are underCompanion, we need to add the container on 10.15+\n                // Grab an array of Application Support paths\n                if #available(OSX 10.15, *) {\n                    let libPaths = NSSearchPathForDirectoriesInDomains(\n                        .libraryDirectory,\n                        .userDomainMask,\n                        true)\n                    appPath = libPaths.first! + \"/Containers/com.apple.ScreenSaver.Engine.legacyScreenSaver/Data/Library/Application Support/\"\n\n                } else {\n                    let appSupportPaths = NSSearchPathForDirectoriesInDomains(\n                        .applicationSupportDirectory,\n                        .userDomainMask,\n                        true)\n\n                    if appSupportPaths.isEmpty {\n                        errorLog(\"FATAL : app support does not exist!\")\n                        return \"/\"\n                    }\n                    appPath = appSupportPaths[0]\n                }\n            }\n        }\n\n        let appSupportDirectory = appPath as NSString\n\n        if aerialFolderExists(at: appSupportDirectory) {\n            processedSupportPath = appSupportDirectory.appendingPathComponent(\"Aerial\")\n            return processedSupportPath\n        } else {\n            debugLog(\"Creating app support directory...\")\n            let asPath = appSupportDirectory.appendingPathComponent(\"Aerial\")\n\n            let fileManager = FileManager.default\n            do {\n                try fileManager.createDirectory(atPath: asPath,\n                                                withIntermediateDirectories: true, attributes: nil)\n\n                processedSupportPath = asPath\n                return asPath\n            } catch let error {\n                errorLog(\"FATAL : Couldn't create app support directory in User directory: \\(error)\")\n                return \"/\"\n            }\n        }\n    }\n\n    /**\n     Returns Aerial's Caches path.\n     \n     + On macOS 10.14 and earlier : `~/Library/Application Support/Aerial/Cache/`\n     + Starting with 10.15 : `~/Library/Containers/com.apple.ScreenSaver.Engine.legacyScreenSaver/Data/Library/Application Support/Aerial/Cache/`\n     \n     - Note: Returns `/` on failure.\n     \n     In some rare instances those system folders may not exist in the container, in this case Aerial can't work.\n     \n     Also note that the shared `Caches` folder, `/Library/Caches/Aerial/`, is no longer user writable in Catalina and will be ignored.\n     */\n    static var path: String = {\n        var path = \"\"\n        /*if PrefsCache.overrideCache {\n            if #available(macOS 12, *) {\n                if let bookmarkData = PrefsCache.cacheBookmarkData {\n                    do {\n                        var isStale = false\n                        let bookmarkUrl = try URL(resolvingBookmarkData: bookmarkData, options: .withSecurityScope, relativeTo: nil, bookmarkDataIsStale: &isStale)\n\n                        debugLog(\"Bookmark is stale : \\(isStale)\")\n                        debugLog(\"\\(bookmarkUrl)\")\n                        path = bookmarkUrl.path\n                        debugLog(\"\\(path)\")\n                    } catch {\n                        errorLog(\"Can't process bookmark\")\n                    }\n                } else {\n                    errorLog(\"Can't find cacheBookmarkData on macOS 12\")\n                }\n            } else {\n                if let customPath = Preferences.sharedInstance.customCacheDirectory {\n                    debugLog(\"Trying \\(customPath)\")\n                    if FileManager.default.fileExists(atPath: customPath) {\n                        path = customPath\n                    } else {\n                        errorLog(\"Could not find your custom Caches path, reverting to default settings\")\n                    }\n                } else {\n                    errorLog(\"Empty path, reverting to default settings\")\n\n                }\n            }\n\n            if path == \"\" {\n                PrefsCache.overrideCache = false\n                path = Cache.supportPath.appending(\"/Cache\")\n            }\n        } else {*/\n\n        path = Cache.supportPath.appending(\"/Cache\")\n        // }\n\n        if FileManager.default.fileExists(atPath: path as String) {\n            return path\n        } else {\n            do {\n                try FileManager.default.createDirectory(atPath: path,\n                                                withIntermediateDirectories: true, attributes: nil)\n                return path\n            } catch let error {\n                errorLog(\"FATAL : Couldn't create Cache directory in Aerial's AppSupport directory: \\(error)\")\n                return \"/\"\n            }\n        }\n    }()\n\n    static var pathUrl: URL = {\n        if #available(macOS 12, *) {\n            if PrefsCache.overrideCache {\n                if let bookmarkData = PrefsCache.cacheBookmarkData {\n                    do {\n                        var isStale = false\n                        let bookmarkUrl = try URL(resolvingBookmarkData: bookmarkData, options: .withSecurityScope, relativeTo: nil, bookmarkDataIsStale: &isStale)\n                        debugLog(\"Bookmark is stale : \\(isStale)\")\n                        debugLog(\"\\(bookmarkUrl)\")\n                        return bookmarkUrl\n                    } catch {\n                        errorLog(\"Can't process bookmark\")\n                    }\n                }\n            }\n        }\n\n        return URL(fileURLWithPath: path)\n    }()\n    /**\n     Returns Aerial's thumbnail cache path, creating it if needed.\n     + On macOS 10.14 and earlier : `~/Library/Application Support/Aerial/Thumbnails/`\n     + Starting with 10.15 : `~/Library/Containers/com.apple.ScreenSaver.Engine.legacyScreenSaver/Data/Library/Application Support/Aerial/Thumbnails/`\n\n     - Note: Returns `/` on failure.\n\n     */\n    static var thumbnailsPath: String = {\n        let path = Cache.supportPath.appending(\"/Thumbnails\")\n\n        if FileManager.default.fileExists(atPath: path as String) {\n            return path\n        } else {\n            do {\n                try FileManager.default.createDirectory(atPath: path,\n                                                withIntermediateDirectories: true, attributes: nil)\n                return path\n            } catch let error {\n                errorLog(\"FATAL : Couldn't create Thumbnails directory in Aerial's AppSupport directory: \\(error)\")\n                return \"/\"\n            }\n        }\n    }()\n\n    /**\n     Returns Aerial's former cache path, if it exists.\n     \n     + On macOS 10.14 and earlier : `~/Library/Caches/Aerial/`\n     + Starting with 10.15 : `~/Library/Containers/com.apple.ScreenSaver.Engine.legacyScreenSaver/Data/Library/Caches/Aerial/`\n     \n     - Note: Returns `nil` on failure.\n    */\n    static private var formerCachePath: String? = {\n        // Grab an array of Cache paths\n        let cacheSupportPaths = NSSearchPathForDirectoriesInDomains(\n            .cachesDirectory,\n            .userDomainMask,\n            true)\n\n        if cacheSupportPaths.isEmpty {\n            errorLog(\"Couldn't find Caches paths!\")\n            return nil\n        }\n\n        let cacheSupportDirectory = cacheSupportPaths[0] as NSString\n        if aerialFolderExists(at: cacheSupportDirectory) {\n            return cacheSupportDirectory.appendingPathComponent(\"Aerial\")\n        } else {\n            do {\n                debugLog(\"trying to create \\(cacheSupportDirectory.appendingPathComponent(\"Aerial\"))\")\n                try FileManager.default.createDirectory(atPath: cacheSupportDirectory.appendingPathComponent(\"Aerial\"),\n                                                withIntermediateDirectories: true, attributes: nil)\n                return path\n            } catch {\n                errorLog(\"Could not create Aerial's Caches path\")\n            }\n            return nil\n        }\n    }()\n\n    // MARK: - Migration from Aerial 1.x.x to 2.x.x\n    /**\n     Migrate files from previous versions of Aerial to the 2.x.x structure.\n     \n     - Moves the video files from Application Support to the `Application Support/Aerial/Cache` sub directory.\n     - Moves the video files from Caches to the `Application Support/Aerial/Cache` sub directory\n     */\n    static func migrate() {\n        if !PrefsCache.overrideCache {\n            migrateAppSupport()\n            migrateOldCache()\n        }\n    }\n\n    /**\n     Migrate video that may be at the root of /Application Support/Aerial/\n     */\n    static private func migrateAppSupport() {\n        let supportURL = URL(fileURLWithPath: supportPath as String)\n        do {\n            let directoryContent = try FileManager.default.contentsOfDirectory(at: supportURL, includingPropertiesForKeys: nil)\n            let videoURLs = directoryContent.filter { $0.pathExtension == \"mov\" }\n\n            if !videoURLs.isEmpty {\n                debugLog(\"Starting migration of your video files from Application Support to the /Cache subfolder\")\n                for videoURL in videoURLs {\n                    debugLog(\"moving \\(videoURL.lastPathComponent)\")\n                    let newURL = URL(fileURLWithPath: path.appending(\"/\\(videoURL.lastPathComponent)\"))\n                    try FileManager.default.moveItem(at: videoURL, to: newURL)\n                }\n                debugLog(\"Migration done.\")\n            }\n        } catch {\n            errorLog(\"Error during migration, please report\")\n            errorLog(error.localizedDescription)\n        }\n    }\n\n    /**\n     Migrate video that may be at the root of a user's /Caches/Aerial/\n     */\n    static private func migrateOldCache() {\n        if let formerCachePath = formerCachePath {\n            do {\n                let formerCacheURL = URL(fileURLWithPath: formerCachePath as String)\n\n                let directoryContent = try FileManager.default.contentsOfDirectory(at: formerCacheURL, includingPropertiesForKeys: nil)\n                let videoURLs = directoryContent.filter { $0.pathExtension == \"mov\" }\n\n                if !videoURLs.isEmpty {\n                    debugLog(\"Starting migration of your video files from Caches to the /Cache subfolder of Application Support\")\n                    for videoURL in videoURLs {\n                        debugLog(\"moving \\(videoURL.lastPathComponent)\")\n                        let newURL = URL(fileURLWithPath: path.appending(\"/\\(videoURL.lastPathComponent)\"))\n                        try FileManager.default.moveItem(at: videoURL, to: newURL)\n                    }\n                    debugLog(\"Migration done.\")\n                }\n            } catch {\n                errorLog(\"Error during migration, please report\")\n                errorLog(error.localizedDescription)\n            }\n        }\n    }\n\n    // Remove files in bad format or outdated\n    static func removeCruft() {\n        // TODO: kind of a temporary safety\n        if VideoList.instance.videos.count > 90 {\n            // First let's look at the cache\n\n            // let pathURL = URL(fileURLWithPath: path)\n            do {\n                guard pathUrl.startAccessingSecurityScopedResource() else {\n                    errorLog(\"removeCruft couldn't access scoped resouce\")\n                    return\n                }\n\n                let directoryContent = try FileManager.default.contentsOfDirectory(at: pathUrl, includingPropertiesForKeys: nil)\n                debugLog(\"count : \\(directoryContent.count)\")\n                let videoURLs = directoryContent.filter { $0.pathExtension == \"mov\" }\n\n                for video in videoURLs {\n                    let filename = video.lastPathComponent\n                    debugLog(\"\\(filename)\")\n                    var found = false\n\n                    // swiftlint:disable for_where\n                    for candidate in VideoList.instance.videos {\n                        if candidate.url.lastPathComponent == filename {\n                            found = true\n                        }\n                    }\n\n                    if !found {\n                        debugLog(\"This file is not in the correct format or outdated, removing : \\(video)\")\n                        try? FileManager.default.removeItem(at: video)\n                    }\n                }\n\n                pathUrl.stopAccessingSecurityScopedResource()\n            } catch {\n                errorLog(\"Error during removing of videos in wrong format, please report\")\n                errorLog(error.localizedDescription)\n            }\n\n            // Also remove uncached cruft\n            removeUncachedCruft()\n        }\n    }\n\n    static func removeUncachedCruft() {\n        for source in SourceList.foundSources where !source.isCachable && source.type != .local {\n            debugLog(\"Checking cruft in \\(source.name)\")\n\n            let pathURL = URL(fileURLWithPath: supportPath.appending(\"/\" + source.name))\n\n            let unprocessed = source.getUnprocessedVideos()\n            debugLog(pathURL.absoluteString)\n\n            do {\n                let directoryContent = try FileManager.default.contentsOfDirectory(at: pathURL, includingPropertiesForKeys: nil)\n                let videoURLs = directoryContent.filter { $0.pathExtension == \"mov\" }\n\n                for video in videoURLs {\n                    let filename = video.lastPathComponent\n                    var found = false\n\n                    // swiftlint:disable for_where\n\n                    for candidate in unprocessed {\n                        if candidate.url.lastPathComponent == filename {\n                            found = true\n                        }\n                    }\n\n                    if !found {\n                        debugLog(\"This file is not in the correct format or outdated, removing : \\(video)\")\n                        try? FileManager.default.removeItem(at: video)\n                    }\n                }\n            } catch {\n                errorLog(\"Error during removal of videos in wrong format, please report\")\n                errorLog(error.localizedDescription)\n            }\n        }\n    }\n\n    /// This clears the whole cache. User beware !\n    static func clearCache() {\n        let pathURL = URL(fileURLWithPath: path)\n        do {\n            let directoryContent = try FileManager.default.contentsOfDirectory(at: pathURL, includingPropertiesForKeys: nil)\n            let videoURLs = directoryContent.filter { $0.pathExtension == \"mov\" }\n\n            for video in videoURLs {\n                try? FileManager.default.removeItem(at: video)\n            }\n        } catch {\n            errorLog(\"Error during removal of videos in wrong format, please report\")\n            errorLog(error.localizedDescription)\n        }\n    }\n\n    static func clearNonCacheableSources() {\n        // Then we need to look at individual online sources\n        // let onlineVideos = VideoList.instance.videos.filter({ !$0.source.isCachable })\n\n        for source in SourceList.foundSources.filter({!$0.isCachable}) {\n            let pathSource = URL(fileURLWithPath: supportPath).appendingPathComponent(source.name)\n            if FileManager.default.fileExists(atPath: pathSource.path) {\n                do {\n                    let directoryContent = try FileManager.default.contentsOfDirectory(at: pathSource, includingPropertiesForKeys: nil)\n\n                    let videoURLs = directoryContent.filter { $0.pathExtension == \"mov\" }\n\n                    for video in videoURLs {\n                        debugLog(\"Removing file : \\(video)\")\n                        try? FileManager.default.removeItem(at: video)\n                    }\n\n                } catch {\n                    errorLog(\"Error during removing of videos in wrong format, please report\")\n                    errorLog(error.localizedDescription)\n                }\n            }\n        }\n\n    }\n\n    // MARK: - About the cache\n    /**\n     Is our cache full ?\n     */\n    static func isFull() -> Bool {\n        return size() > PrefsCache.cacheLimit\n    }\n\n    /**\n     Do we still have a bit of free space (0.5 GB)\n     */\n    static func hasSomeFreeSpace() -> Bool {\n        return size() < PrefsCache.cacheLimit - 0.5\n    }\n\n    /**\n     Returns the cache size in GB as a string (eg. 5.1 GB)\n     */\n    static func sizeString() -> String {\n        let pathURL = Foundation.URL(fileURLWithPath: path)\n\n        // check if the url is a directory\n        if (try? pathURL.resourceValues(forKeys: [.isDirectoryKey]))?.isDirectory == true {\n            var folderSize = 0\n            (FileManager.default.enumerator(at: pathURL, includingPropertiesForKeys: nil)?.allObjects as? [URL])?.lazy.forEach {\n                folderSize += (try? $0.resourceValues(forKeys: [.totalFileAllocatedSizeKey]))?.totalFileAllocatedSize ?? 0\n            }\n            let byteCountFormatter =  ByteCountFormatter()\n            byteCountFormatter.allowedUnits = .useGB\n            byteCountFormatter.countStyle = .file\n            let sizeToDisplay = byteCountFormatter.string(for: folderSize) ?? \"\"\n            return sizeToDisplay\n        }\n\n        // In case it fails somehow\n        return \"No cache found\"\n    }\n\n    // MARK: - Helpers\n    /**\n     Does an `/Aerial/` subfolder exist inside the given path\n     - parameter at: Source path\n     - returns: Path existance as a Bool.\n     */\n    private static func aerialFolderExists(at: NSString) -> Bool {\n        let aerialFolder = at.appendingPathComponent(\"Aerial\")\n        return FileManager.default.fileExists(atPath: aerialFolder as String)\n    }\n\n    /**\n     Returns cache size in GB\n     */\n    static func size() -> Double {\n        let pathURL = URL(fileURLWithPath: path)\n\n        // check if the url is a directory\n        if (try? pathURL.resourceValues(forKeys: [.isDirectoryKey]))?.isDirectory == true {\n            var folderSize = 0\n            (FileManager.default.enumerator(at: pathURL, includingPropertiesForKeys: nil)?.allObjects as? [URL])?.lazy.forEach {\n                folderSize += (try? $0.resourceValues(forKeys: [.totalFileAllocatedSizeKey]))?.totalFileAllocatedSize ?? 0\n            }\n\n            return Double(folderSize) / 1000000000\n        }\n\n        return 0\n    }\n\n    static func getDirectorySize(directory: String) -> Double {\n        if FileManager.default.fileExists(atPath: directory) {\n            let pathURL = URL(fileURLWithPath: directory)\n\n            // check if the url is a directory\n            if (try? pathURL.resourceValues(forKeys: [.isDirectoryKey]))?.isDirectory == true {\n                var folderSize = 0\n                (FileManager.default.enumerator(at: pathURL, includingPropertiesForKeys: nil)?.allObjects as? [URL])?.lazy.forEach {\n                    folderSize += (try? $0.resourceValues(forKeys: [.totalFileAllocatedSizeKey]))?.totalFileAllocatedSize ?? 0\n                }\n\n                return Double(folderSize) / 1000000000\n            }\n\n            return 0\n        } else {\n            return 0\n        }\n    }\n\n    static func packsSize() -> Double {\n        var totalSize: Double = 0\n        for source in SourceList.foundSources where !source.isCachable {\n            let sourcePath = supportPath.appending(\"/\" + source.name)\n            totalSize += getDirectorySize(directory: sourcePath)\n        }\n\n        return totalSize\n    }\n\n    // swiftlint:disable line_length\n    // MARK: Networking restrictions for cache\n    /**\n     Can we download a file ?\n     \n     Depending on user's settings, the cache may be full or the user may not be on a trusted network.\n     - Note: If a user disabled cache management (full manual mode), this will always be true.\n     - parameter action: A closure with the action to be accomplished should the conditions be met.\n     */\n    static func ensureDownload(action: @escaping () -> Void) {\n        // Do we manage the cache or not ?\n        if PrefsCache.enableManagement {\n            // Check network first\n            if !canNetwork() {\n                if !Aerial.helper.showAlert(question: \"You are on a restricted WiFi network\",\n                             text: \"Your current settings restrict downloads when not connected to a trusted network. Do you wish to proceed?\\n\\nReminder: You can change this setting in the Cache tab.\",\n                             button1: \"Download Anyway\",\n                             button2: \"Cancel\") {\n                    return\n                }\n            }\n\n            // Then cache status\n            if isFull() {\n                let formatter = NumberFormatter()\n                formatter.locale = Locale.current // USA: Locale(identifier: \"en_US\")\n                formatter.numberStyle = .decimal\n                let result = formatter.string(from: NSNumber(value: PrefsCache.cacheLimit.rounded(toPlaces: 1)))!\n                //print(result)   // -> US$9,999.99\n                \n                if !Aerial.helper.showAlert(question: \"Your cache is full\",\n                                            text: \"Your cache limit is currently set to \\(result) GB, and currently contains \\(Cache.sizeString()) of files.\\n\\n Do you want to proceed with the download anyway?\\n\\nYou can manually increase or decrease your cache size in Settings > Cache.\",\n                             button1: \"Download Anyway\",\n                             button2: \"Cancel\") {\n                    return\n                }\n            }\n        }\n\n        // If all is fine then proceed\n        action()\n    }\n\n    /**\n    Can we safely use network ?\n    \n    Depending on user's settings, they may not be on a trusted network.\n    - Note: If a user disabled cache management (full manual mode), this will always be true.\n    */\n    static func canNetwork() -> Bool {\n        if !PrefsCache.enableManagement {\n            return true\n        }\n\n        if PrefsCache.restrictOnWiFi {\n            // If we are not connected to WiFi we allow\n            if Cache.ssid == \"\" || PrefsCache.allowedNetworks.contains(ssid) {\n                return true\n            } else {\n                return false\n            }\n        } else {\n            return true\n        }\n    }\n\n    static func outdatedVideos() -> [AerialVideo] {\n        guard PrefsCache.enableManagement else {\n            return []\n        }\n\n        var cutoffDate = Date()\n        switch PrefsCache.cachePeriodicity {\n        case .daily:\n            cutoffDate = Calendar.current.date(byAdding: .day, value: -1, to: cutoffDate)!\n        case .weekly:\n            cutoffDate = Calendar.current.date(byAdding: .day, value: -7, to: cutoffDate)!\n        case .monthly:\n            cutoffDate = Calendar.current.date(byAdding: .month, value: -1, to: cutoffDate)!\n        case .never:\n            return []\n        }\n\n        // Get a list of cached videos that are not favorites, and are from a cacheable source (not a pack)\n        // Yes this is getting a bit complicated\n        var evictable: [Date: AerialVideo] = [:]\n        let currentlyCached = VideoList.instance.videos.filter({ $0.isAvailableOffline && $0.source.isCachable && !PrefsVideos.favorites.contains($0.id)})\n\n        for video in currentlyCached {\n            let path = VideoCache.cachePath(forVideo: video)!\n\n            // swiftlint:disable:next force_try\n            let attributes = try! FileManager.default.attributesOfItem(atPath: path)\n            let creationDate = attributes[.creationDate] as! Date\n\n            if creationDate < cutoffDate {\n                evictable[creationDate] = video\n            }\n        }\n\n        return  evictable.sorted { $0.key < $1.key }.map({ $0.value })\n    }\n\n    // swiftlint:disable:next cyclomatic_complexity\n    static func freeCache() {\n        guard PrefsCache.enableManagement else {\n            return\n        }\n\n\n        // Step 1 : Delete hidden videos\n        debugLog(\"Looking for hidden videos to delete...\")\n        for video in VideoList.instance.videos.filter({ PrefsVideos.hidden.contains($0.id) && $0.isAvailableOffline }) {\n            debugLog(\"Deleting hidden video \\(video.secondaryName)\")\n            do {\n                let path = VideoList.instance.localPathFor(video: video)\n                try FileManager.default.removeItem(atPath: path)\n            } catch {\n                errorLog(\"Could not delete video : \\(video.secondaryName)\")\n            }\n        }\n\n        // We may be good ?\n        if hasSomeFreeSpace() {\n            return\n        }\n\n        // Step 2 : Delete videos that are out of rotation\n        let evictables = outdatedVideos()\n\n        if evictables.isEmpty {\n            debugLog(\"No outdated videos, we won't delete anything\")\n            return\n        }\n\n        debugLog(\"Looking for outdated videos that aren't in rotation (candidates : \\(evictables.count)\")\n\n        outerLoop: for video in evictables {\n            if VideoList.instance.currentRotation().contains(video) {\n                // Outdated but in rotation, so keep it !\n                // debugLog(\"outdated but in rotation \\(video.secondaryName)\")\n            } else {\n                debugLog(\"Removing outdated video not in rotation \\(video.secondaryName)\")\n                do {\n                    try FileManager.default.removeItem(atPath: VideoCache.cachePath(forVideo: video)!)\n                } catch {\n                    errorLog(\"Could not delete video : \\(video.secondaryName)\")\n                }\n\n                if hasSomeFreeSpace() {\n                    // Removed enough\n                    break outerLoop\n                }\n            }\n        }\n\n        // Are we there yeeeet ?\n        if hasSomeFreeSpace() {\n            return\n        }\n\n        debugLog(\"Looking for outdated videos that may still be in rotation (candidates : \\(evictables.count)\")\n\n        var currentVideos = [AerialVideo]()\n\n        for view in AerialView.instanciatedViews {\n            if let video = view.currentVideo {\n                currentVideos.append(video)\n            }\n        }\n\n        outerLoop2: for video in evictables {\n            if currentVideos.contains(video) {\n                debugLog(\"\\(video.secondaryName) is currently playing, trying another\")\n            } else {\n                debugLog(\"Removing outdated video that was in rotation \\(video.secondaryName)\")\n                do {\n                    try FileManager.default.removeItem(atPath: VideoCache.cachePath(forVideo: video)!)\n                } catch {\n                    errorLog(\"Could not delete video : \\(video.secondaryName)\")\n                }\n\n                if hasSomeFreeSpace() {\n                    // Removed enough\n                    break outerLoop2\n                }\n            }\n        }\n\n        // At this point we can't do more \n    }\n\n    static func fillOrRollCache() {\n        guard PrefsCache.enableManagement && canNetwork() else {\n            return\n        }\n\n        // Grab a *shuffled* list of uncached in rotation videos\n        let rotation = VideoList.instance.currentRotation().filter { !$0.isAvailableOffline }.shuffled()\n\n        if rotation.isEmpty {\n            debugLog(\"> Current playlist is already fully cached, no download/rotation needed\")\n            return\n        }\n\n        debugLog(\"> Fill or roll cache\")\n        // Do we have some space to download at least a video (by default .5 GB) ?\n        if !hasSomeFreeSpace() {\n            freeCache()\n\n            if !hasSomeFreeSpace() {\n                debugLog(\"No free space to reclaim currently.\")\n                return\n            }\n        }\n\n        debugLog(\"Uncached videos in rotation : \\(rotation.count)\")\n\n        // We may be satisfied already\n        if rotation.isEmpty {\n            return\n        }\n\n        // Queue the first video on the list\n        debugLog(\"Queuing video : \\(rotation.first!.secondaryName)\")\n        VideoManager.sharedInstance.queueDownload(rotation.first!)\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Models/Cache/PoiStringProvider.swift",
    "content": "//\n//  PoiStringProvider.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 13/10/2018.\n//  Copyright © 2018 John Coates. All rights reserved.\n//\n\nimport Foundation\n\nfinal class CommunityStrings {\n    let id: String\n    let name: String\n    let poi: [String: String]\n\n    init(id: String, name: String, poi: [String: String]) {\n        self.id = id\n        self.name = name\n        self.poi = poi\n    }\n}\n\nfinal class PoiStringProvider {\n    static let sharedInstance = PoiStringProvider()\n    var loadedDescriptions = false\n    var loadedDescriptionsWasLocalized = false\n\n    var stringBundle: Bundle?\n    var stringDict: [String: String]?\n\n    var communityStrings = [CommunityStrings]()\n    var communityLanguage = \"\"\n    // MARK: - Lifecycle\n    init() {\n        debugLog(\"Poi Strings Provider initialized\")\n        loadBundle()\n        loadCommunity()\n    }\n\n    // MARK: - Bundle management\n    private func getBundleLanguages() -> [String] {\n        // Might want to improve that...\n        // This is a static list of what's supposed to be in the bundle\n        // swiftlint:disable:next line_length\n        return [\"de\", \"he\", \"en_AU\", \"ar\", \"el\", \"ja\", \"en\", \"uk\", \"es_419\", \"zh_CN\", \"es\", \"pt_BR\", \"da\", \"it\", \"sk\", \"pt_PT\", \"ms\", \"sv\", \"cs\", \"ko\", \"no\", \"hu\", \"zh_HK\", \"tr\", \"pl\", \"zh_TW\", \"en_GB\", \"vi\", \"ru\", \"fr_CA\", \"fr\", \"fi\", \"id\", \"nl\", \"th\", \"pt\", \"ro\", \"hr\", \"hi\", \"ca\"]\n    }\n\n    private func loadBundle() {\n        // Idle string bundle\n        var bundlePath = Cache.supportPath.appending(\"/macOS 26\")\n\n        if PrefsAdvanced.ciOverrideLanguage == \"\" {\n            debugLog(\"Preferred languages : \\(Locale.preferredLanguages)\")\n\n            let bestMatchedLanguage = Bundle.preferredLocalizations(from: getBundleLanguages(), forPreferences: Locale.preferredLanguages).first\n            if let match = bestMatchedLanguage {\n                debugLog(\"Best matched language : \\(match)\")\n                bundlePath.append(contentsOf: \"/TVIdleScreenStrings.bundle/\" + match + \".lproj/\")\n            } else {\n                debugLog(\"No match, reverting to english\")\n                // We load the bundle and let system grab the closest available preferred language\n                // This no longer works in Catalina and defaults back to english\n                // as legacyScreenSaver.appex, our new \"mainbundle\" is english only\n                bundlePath.append(contentsOf: \"/TVIdleScreenStrings.bundle\")\n            }\n        } else {\n            let bestMatchedLanguage = Bundle.preferredLocalizations(from: getBundleLanguages(), forPreferences:  [PrefsAdvanced.ciOverrideLanguage]).first\n            \n            if let match = bestMatchedLanguage {\n                debugLog(\"Best matched language : \\(match)\")\n                bundlePath.append(contentsOf: \"/TVIdleScreenStrings.bundle/\" + match + \".lproj/\")\n            } else {\n                debugLog(\"No match, reverting to english\")\n                // We load the bundle and let system grab the closest available preferred language\n                // This no longer works in Catalina and defaults back to english\n                // as legacyScreenSaver.appex, our new \"mainbundle\" is english only\n                bundlePath.append(contentsOf: \"/TVIdleScreenStrings.bundle\")\n            }\n            \n            /*debugLog(\"Language overriden to \\(String(describing: bestMatchedLanguage))\")\n            // Or we load the overriden one\n            bundlePath.append(contentsOf: \"/TVIdleScreenStrings.bundle/\" + PrefsAdvanced.ciOverrideLanguage + \".lproj/\")*/\n        }\n\n        if let sb = Bundle.init(path: bundlePath) {\n            let dictPath = Cache.supportPath.appending(\"/macOS 26/TVIdleScreenStrings.bundle/en.lproj/Localizable.nocache.strings\")\n\n            // We could probably only work with that...\n            if let sd = NSDictionary(contentsOfFile: dictPath) as? [String: String] {\n                self.stringDict = sd\n            }\n\n            self.stringBundle = sb\n            self.loadedDescriptions = true\n        } else {\n            errorLog(\"TVIdleScreenStrings.bundle is missing, please remove entries.json in Cache folder to fix the issue\")\n        }\n    }\n\n    // Make sure we have the correct bundle loaded\n    private func ensureLoadedBundle() -> Bool {\n        if loadedDescriptions {\n            return true\n        } else {\n            loadBundle()\n            return loadedDescriptions\n        }\n    }\n\n    // Return the Localized (or english) string for a key from the Strings Bundle\n    func getString(key: String, video: AerialVideo) -> String {\n        guard ensureLoadedBundle() else { return \"\" }\n\n        /*let preferences = Preferences.sharedInstance\n        let locale: NSLocale = NSLocale(localeIdentifier: Locale.preferredLanguages[0])\n\n        if #available(OSX 10.12, *) {\n            if preferences.localizeDescriptions && locale.languageCode != communityLanguage && preferences.ciOverrideLanguage == \"\" {\n                return stringBundle!.localizedString(forKey: key, value: \"\", table: \"Localizable.nocache\")\n            }\n        }*/\n\n        if !video.communityPoi.isEmpty {\n            return key  // We directly store the string in the key\n        } else {\n            return stringBundle!.localizedString(forKey: key, value: \"\", table: \"Localizable.nocache\")\n        }\n    }\n\n    // Return all POIs for an id\n    func fetchExtraPoiForId(id: String) -> [String: String]? {\n        guard let stringDict = stringDict, ensureLoadedBundle() else { return [:] }\n\n        var found = [String: String]()\n        for key in stringDict.keys where key.starts(with: id) {\n            found[String(key.split(separator: \"_\").last!)] = key // FIXME: crash if key doesn't have \"_\"\n        }\n\n        return found\n    }\n\n    // \n    func getPoiKeys(video: AerialVideo) -> [String: String] {\n        if !video.communityPoi.isEmpty {\n            return video.communityPoi\n        } else {\n            return video.poi\n        }\n    }\n\n    // Do we have any keys, anywhere, for said video ?\n    func hasPoiKeys(video: AerialVideo) -> Bool {\n        return (!video.poi.isEmpty && loadedDescriptions) ||\n        (!video.communityPoi.isEmpty && !getPoiKeys(video: video).isEmpty)\n    }\n\n    func getLocalizedNameKey(key: String) -> String {\n        guard ensureLoadedBundle() else { return \"\" }\n        \n        return stringBundle!.localizedString(forKey: key, value: \"\", table: \"Localizable.nocache\")\n    }\n    \n    // MARK: - Community data\n    // siftlint:disable:next cyclomatic_complexity\n    private func getCommunityPathForLocale() -> String {\n        let locale: NSLocale = NSLocale(localeIdentifier: Locale.preferredLanguages[0])\n\n        // Do we have a language override ?\n        if PrefsAdvanced.ciOverrideLanguage != \"\" {\n            let path = Bundle(for: PoiStringProvider.self).path(forResource: PrefsAdvanced.ciOverrideLanguage, ofType: \"json\")\n            if path != nil {\n                let fileManager = FileManager.default\n                if fileManager.fileExists(atPath: path!) {\n                    debugLog(\"Community Language overriden to : \\(PrefsAdvanced.ciOverrideLanguage)\")\n                    communityLanguage = PrefsAdvanced.ciOverrideLanguage\n                    return path!\n                }\n            }\n        }\n\n        if #available(OSX 10.12, *) {\n            // First we look in the Cache Folder for a locale directory\n            let cacheDirectory = Cache.supportPath\n            var cacheResourcesString = cacheDirectory\n            cacheResourcesString.append(contentsOf: \"/locale\")\n            let cacheUrl = URL(fileURLWithPath: cacheResourcesString)\n\n            if cacheUrl.hasDirectoryPath {\n                debugLog(\"Aerial cache directory contains /locale\")\n\n                let cc = locale.languageCode\n                debugLog(\"Looking for \\(cc).json\")\n\n                let fileUrl = URL(fileURLWithPath: cacheResourcesString.appending(\"/\\(cc).json\"))\n                debugLog(fileUrl.absoluteString)\n                let fileManager = FileManager.default\n                if fileManager.fileExists(atPath: fileUrl.path) {\n                    debugLog(\"Locale description found\")\n                    communityLanguage = cc\n                    return fileUrl.path\n                } else {\n                    debugLog(\"Locale description not found\")\n                }\n            }\n            debugLog(\"Defaulting to bundle\")\n            let cc = locale.languageCode\n\n            let path = Bundle(for: PoiStringProvider.self).path(forResource: cc, ofType: \"json\")\n            if path != nil {\n                let fileManager = FileManager.default\n                if fileManager.fileExists(atPath: path!) {\n                    communityLanguage = cc\n                    return path!\n                }\n            }\n        }\n\n        // Fallback to english in bundle\n        communityLanguage = \"en\"\n        return Bundle(for: PoiStringProvider.self).path(forResource: \"en\", ofType: \"json\")!\n    }\n\n    // Load the community strings\n    private func loadCommunity() {\n        let bundlePath = getCommunityPathForLocale()\n        debugLog(\"path : \\(bundlePath)\")\n\n        do {\n            let data = try Data(contentsOf: URL(fileURLWithPath: bundlePath), options: .mappedIfSafe)\n            let batches = try JSONSerialization.jsonObject(with: data, options: .allowFragments)\n\n            guard let batch = batches as? NSDictionary else {\n                errorLog(\"Community : Encountered unexpected content type for batch, please report !\")\n                return\n            }\n\n            for item in batch {\n                let id = item.key as! String\n                let name = (item.value as! NSDictionary)[\"name\"] as! String\n                let poi = (item.value as! NSDictionary)[\"pointsOfInterest\"] as? [String: String]\n\n                communityStrings.append(CommunityStrings(id: id, name: name, poi: poi ?? [:]))\n            }\n        } catch {\n            // handle error\n            errorLog(\"Community JSON ERROR : \\(error)\")\n        }\n        debugLog(\"Community JSON : \\(communityStrings.count) entries\")\n    }\n\n    func getCommunityName(id: String) -> String? {\n        return communityStrings.first(where: { $0.id == id }).map { $0.name }\n    }\n\n    func getCommunityPoi(id: String) -> [String: String] {\n        return communityStrings.first(where: { $0.id == id }).map { $0.poi } ?? [:]\n    }\n\n    // Helpers for the main popup\n    // swiftlint:disable:next cyclomatic_complexity\n    func getLanguagePosition() -> Int {\n        // The list is alphabetized based on their english name in the UI\n        switch PrefsAdvanced.ciOverrideLanguage {\n        case \"ar\":  // Arabic\n            return 1\n        case \"zh_CN\":  // Chinese Simplified\n            return 2\n        case \"zh_TW\":  // Chinese Traditional\n            return 3\n        case \"nl\":  // Dutch\n            return 4\n        case \"en\":  // English\n            return 5\n        case \"fr\":  // French\n            return 6\n        case \"de\":  // German\n            return 7\n        case \"he\":  // Hebrew\n            return 8\n        case \"hu\":  // Hungarian\n            return 9\n        case \"it\":  // Italian\n            return 10\n        case \"ja\":  // Japanese\n            return 11\n        case \"ko\":  // Korean\n            return 12\n        case \"pl\":  // Polish\n            return 13\n        case \"pt\":  // Portuguese\n            return 14\n        case \"pt_BR\":  // Portuguese (Brazil)\n            return 15\n        case \"ru\":  // Russian\n            return 16\n        case \"es\":  // Spanish\n            return 17\n        case \"sv\":  // Swedish\n            return 18\n        case \"tl\":  // Tagalog\n            return 19\n        default:    // This is the default, preferred language\n            return 0\n        }\n    }\n\n    // swiftlint:disable:next cyclomatic_complexity\n    func getLanguageStringFromPosition(pos: Int) -> String {\n        switch pos {\n        case 1:\n            return \"ar\"\n        case 2:\n            return \"zh_CN\"\n        case 3:\n            return \"zh_TW\"\n        case 4:\n            return \"nl\"\n        case 5:\n            return \"en\"\n        case 6:\n            return \"fr\"\n        case 7:\n            return \"de\"\n        case 8:\n            return \"he\"\n        case 9:\n            return \"hu\"\n        case 10:\n            return \"it\"\n        case 11:\n            return \"ja\"\n        case 12:\n            return \"ko\"\n        case 13:\n            return \"pl\"\n        case 14:\n            return \"pt\"\n        case 15:\n            return \"pt_BR\"\n        case 16:\n            return \"ru\"\n        case 17:\n            return \"es\"\n        case 18:\n            return \"sv\"\n        case 19:\n            return \"tl\"\n        default:\n            return \"\"\n        }\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Models/Cache/Thumbnails.swift",
    "content": "//\n//  Thumbnails.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 20/07/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Cocoa\nimport AVKit\n\nstruct Thumbnails {\n    static let thumbSize = CGSize.init(width: 192, height: 108)\n\n    /**\n     Generate thumbnails for the videos\n     \n     When a video is not available offline, it will also save a larger version\n     of the first frame of the video, to be used later in the UI as a placeholder\n     */\n\n    /*\n    static func generateAllThumbnails(forVideos videos: [AerialVideo]) {\n        print(\"starting thumb generation\")\n        for video in videos {\n            if cached(forVideo: video) == nil {\n                DispatchQueue.global().async {\n                    generate(forVideo: video)\n                }\n            }\n        }\n        print(\"/thumb generation\")\n    }*/\n\n    /**\n     Generate a thumbnail for the video\n     \n     When a video is not available offline, it will also save a larger version\n     of the first frame of the video, to be used later in the UI as a placeholder\n     */\n    static func generate(forVideo video: AerialVideo) {\n        do {\n            var asset: AVURLAsset\n            if video.isAvailableOffline {\n                // If a video is already cached, we may still need to use an online fetch as there's a bug\n                // with AVAssetImageGenerator and Dolby Vision files\n                if (PrefsVideos.videoFormat == .v1080pHDR || PrefsVideos.videoFormat == .v4KHDR) && video.source.name.starts(with: \"tvOS\") {\n                    // We workaround here by grabbing online a 1080 SDR instead\n                    let urlHEVC = video.urls[.v1080pHEVC]\n                    let url264 = video.urls[.v1080pH264]\n                    if urlHEVC != nil && urlHEVC != \"\" {\n                        asset = AVURLAsset(url: URL(string: urlHEVC!)!)\n                    } else if url264 != nil && url264 != \"\" {\n                        asset = AVURLAsset(url: URL(string: url264!)!)\n                    } else {\n                        // Well...\n                        asset = AVURLAsset(url: video.url)\n                    }\n                } else {\n                    // let path = VideoCache.cachePath(forVideo: video)!\n                    let path = VideoList.instance.localPathFor(video: video)\n                    asset = AVURLAsset(url: URL(fileURLWithPath: path))\n                }\n            } else {\n                if (PrefsVideos.videoFormat == .v1080pHDR || PrefsVideos.videoFormat == .v4KHDR) && video.source.name.starts(with: \"tvOS\") {\n                    // We workaround here by grabbing online a 1080 SDR instead\n                    let urlHEVC = video.urls[.v1080pHEVC]\n                    let url264 = video.urls[.v1080pH264]\n                    if urlHEVC != nil && urlHEVC != \"\" {\n                        asset = AVURLAsset(url: URL(string: urlHEVC!)!)\n                    } else if url264 != nil && url264 != \"\" {\n                        asset = AVURLAsset(url: URL(string: url264!)!)\n                    } else {\n                        // Well...\n                        asset = AVURLAsset(url: video.url)\n                    }\n                } else {\n                    asset = AVURLAsset(url: video.url)\n                }\n            }\n\n            // maybe that doesn't work great with HDR, or a Big Sur thing ?\n            let imageGenerator = AVAssetImageGenerator(asset: asset)\n            imageGenerator.appliesPreferredTrackTransform = true\n\n            let cgImage = try imageGenerator.copyCGImage(at: .zero,\n                                                         actualTime: nil)\n\n            let saveURL = URL(fileURLWithPath: getPath(forVideo: video))\n\n            try writeImage(image: NSImage(cgImage: cgImage, size: thumbSize),\n                           usingType: .png,\n                           withSizeInPixels: thumbSize,\n                           to: saveURL)\n\n            let largeURL = URL(fileURLWithPath: getLargePath(forVideo: video))\n            let fullSize = CGSize.init(width: cgImage.width, height: cgImage.height)\n\n            try writeImage(image: NSImage(cgImage: cgImage, size: fullSize),\n                           usingType: .jpeg,\n                           withSizeInPixels: fullSize,\n                           to: largeURL)\n        } catch {\n            errorLog(error.localizedDescription)\n        }\n    }\n\n    static private func unscaledBitmapImageRep(forImage image: NSImage) -> NSBitmapImageRep {\n        guard let rep = NSBitmapImageRep(\n            bitmapDataPlanes: nil,\n            pixelsWide: Int(image.size.width),\n            pixelsHigh: Int(image.size.height),\n            bitsPerSample: 8,\n            samplesPerPixel: 4,\n            hasAlpha: true,\n            isPlanar: false,\n            colorSpaceName: .deviceRGB,\n            bytesPerRow: 0,\n            bitsPerPixel: 0\n            ) else {\n                preconditionFailure()\n        }\n\n        NSGraphicsContext.saveGraphicsState()\n        NSGraphicsContext.current = NSGraphicsContext(bitmapImageRep: rep)\n        image.draw(at: .zero, from: .zero, operation: .sourceOver, fraction: 1.0)\n        NSGraphicsContext.restoreGraphicsState()\n\n        return rep\n    }\n\n    static private func writeImage(\n        image: NSImage,\n        usingType type: NSBitmapImageRep.FileType,\n        withSizeInPixels size: NSSize?,\n        to url: URL) throws {\n        if let size = size {\n            image.size = size\n        }\n        let rep = unscaledBitmapImageRep(forImage: image)\n\n        guard let data = rep.representation(using: type, properties: [.compressionFactor: 0.8]) else {\n            preconditionFailure()\n        }\n\n        try data.write(to: url)\n    }\n\n    /**\n     \n     */\n    static func cached(forVideo video: AerialVideo) -> NSImage? {\n        let candidateThumb = getPath(forVideo: video)\n        if FileManager.default.fileExists(atPath: candidateThumb) {\n            return NSImage(contentsOfFile: candidateThumb)\n        } else {\n            return nil\n        }\n    }\n\n    static private func getPath(forVideo video: AerialVideo) -> String {\n        return Cache.thumbnailsPath.appending(\"/\"+video.id+\".png\")\n    }\n\n    static private func getLargePath(forVideo video: AerialVideo) -> String {\n        return Cache.thumbnailsPath.appending(\"/\"+video.id+\"-large.jpg\")\n    }\n\n    static func get(forVideo video: AerialVideo, _ completion: @escaping ((_ image: NSImage?) -> Void)) {\n        if let thumb = cached(forVideo: video) {\n            completion(thumb)\n        } else if video.isAvailableOffline {\n            DispatchQueue.global().async {\n                generate(forVideo: video)\n\n                // Completion on the main queue\n                DispatchQueue.main.async {\n                    completion(cached(forVideo: video))\n                }\n            }\n        } else {\n            if Cache.canNetwork() {\n                DispatchQueue.global().async {\n                    generate(forVideo: video)\n\n                    DispatchQueue.main.async {\n                        completion(cached(forVideo: video))\n                    }\n                }\n            } else {\n                completion(nil)\n            }\n        }\n    }\n\n    static func getLarge(forVideo video: AerialVideo, _ completion: @escaping ((_ image: NSImage?) -> Void)) {\n        let candidateLarge = getLargePath(forVideo: video)\n        if FileManager.default.fileExists(atPath: candidateLarge) {\n            return completion(NSImage(contentsOfFile: candidateLarge))\n        } else {\n            // This may happen in a race...\n            return completion(nil)\n        }\n    }\n\n    static func getLargeURL(forVideo video: AerialVideo) -> URL? {\n        let candidateLarge = getLargePath(forVideo: video)\n\n        if FileManager.default.fileExists(atPath: candidateLarge) {\n            return URL(fileURLWithPath: candidateLarge)\n        } else {\n            // This may happen in a race...\n            return nil\n        }\n\n    }\n\n}\n"
  },
  {
    "path": "Aerial/Source/Models/Cache/TimeMachine.swift",
    "content": "//\n//  TimeMachine.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 13/09/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Foundation\n\nstruct TimeMachine {\n\n    static func isExcluded() -> Bool {\n        let process: Process = Process()\n\n        debugLog(\"Checking if our path \\(Cache.path) is excluded in Time Machine\")\n\n        process.launchPath = \"/usr/bin/tmutil\"\n        process.arguments = [\"isexcluded\", Cache.path]\n\n        let pipe = Pipe()\n        process.standardOutput = pipe\n        process.standardError = pipe\n\n        process.launch()\n        let data = pipe.fileHandleForReading.readDataToEndOfFile()\n        let output = String(data: data, encoding: .utf8)\n        debugLog(output ?? \"No output from tmutil\")\n        process.waitUntilExit()\n\n        // Now parse output if any, we're looking for \"Excluded\" string\n        // Tested on 10.14/10.16, should be \"safe\" even if it doesn't work on other oses\n        if let output = output {\n            return output.contains(\"Excluded\")\n        } else {\n            return false\n        }\n    }\n\n    static func exclude() {\n        let process: Process = Process()\n\n        debugLog(\"Trying to exclude our path \\(Cache.path) in Time Machine\")\n\n        process.launchPath = \"/usr/bin/tmutil\"\n        process.arguments = [\"addexclusion\", Cache.path]\n\n        let pipe = Pipe()\n        process.standardOutput = pipe\n        process.standardError = pipe\n\n        process.launch()\n        let data = pipe.fileHandleForReading.readDataToEndOfFile()\n        let output = String(data: data, encoding: .utf8)\n        debugLog(output ?? \"No output from tmutil\")\n\n        process.waitUntilExit()\n    }\n\n    static func reinclude() {\n        let process: Process = Process()\n\n        debugLog(\"Trying to reinclude our path \\(Cache.path) in Time Machine\")\n\n        process.launchPath = \"/usr/bin/tmutil\"\n        process.arguments = [\"removeexclusion\", Cache.path]\n\n        let pipe = Pipe()\n        process.standardOutput = pipe\n        process.standardError = pipe\n\n        process.launch()\n        let data = pipe.fileHandleForReading.readDataToEndOfFile()\n        let output = String(data: data, encoding: .utf8)\n        debugLog(output ?? \"No output from tmutil\")\n\n        process.waitUntilExit()\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Models/Cache/VideoCache.swift",
    "content": "//\n//  VideoCache.swift\n//  Aerial\n//\n//  Created by John Coates on 10/29/15.\n//  Copyright © 2015 John Coates. All rights reserved.\n//\n\nimport Foundation\nimport AVFoundation\nimport ScreenSaver\n\nfinal class VideoCache {\n    var videoData: Data\n    var mutableVideoData: NSMutableData?\n    var loading: Bool\n    var loadedRanges: [NSRange] = []\n    let URL: URL\n\n    static var computedCacheDirectory: String?\n    static var computedAppSupportDirectory: String?\n\n    // MARK: - Application Support directory\n    static var appSupportDirectory: String? {\n        // TODO : temporary for the migration\n        return Cache.supportPath\n//\n//        // We only process this once if successful\n//        if computedAppSupportDirectory != nil {\n//            return computedAppSupportDirectory\n//        }\n//\n//        var foundDirectory: String?\n//\n//        let appSupportPaths = NSSearchPathForDirectoriesInDomains(.applicationSupportDirectory,\n//                                                                 .userDomainMask,\n//                                                                 true)\n//\n//        if appSupportPaths.isEmpty {\n//            errorLog(\"Couldn't find appSupport paths!\")\n//            return nil\n//        }\n//        let appSupportDirectory = appSupportPaths[0] as NSString\n//        if aerialFolderExists(at: appSupportDirectory) {\n//            debugLog(\"app support exists\")\n//            foundDirectory = appSupportDirectory.appendingPathComponent(\"Aerial\")\n//        } else {\n//            debugLog(\"creating app support directory\")\n//            // We create in user appSupport which may be containairized\n//            // so ~/Library/Application Support/ on pre 10.15\n//            // or ~/Library/Containers/com.apple.ScreenSaver.Engine.legacyScreenSaver\n//            //    /Data/Library/Application Support/\n//            foundDirectory = appSupportDirectory.appendingPathComponent(\"Aerial\")\n//\n//            let fileManager = FileManager.default\n//            if fileManager.fileExists(atPath: foundDirectory!) == false {\n//                do {\n//                    try fileManager.createDirectory(atPath: foundDirectory!,\n//                                                    withIntermediateDirectories: false, attributes: nil)\n//                } catch let error {\n//                    errorLog(\"Couldn't create appSupport directory in User directory: \\(error)\")\n//                    errorLog(\"FATAL : There's nothing more we can do at this point\")\n//                    return nil\n//                }\n//            }\n//        }\n//\n//        // Cache the computed value\n//        computedAppSupportDirectory = foundDirectory\n//        return computedAppSupportDirectory\n    }\n\n    // MARK: - User Video cache directory\n    static var cacheDirectory: String? {\n        // TODO : Until refactor is done\n        return Cache.path\n\n//        // We only process this once if successful\n//        if computedCacheDirectory != nil {\n//            return computedCacheDirectory\n//        }\n//\n//        var cacheDirectory: String?\n//        let preferences = Preferences.sharedInstance\n//\n//        if let customCacheDirectory = preferences.customCacheDirectory {\n//            // We may have overriden the cache directory, but it may no longer exist !\n//            if FileManager.default.fileExists(atPath: customCacheDirectory as String) {\n//                debugLog(\"Using exiting customCacheDirectory : \\(customCacheDirectory)\")\n//                cacheDirectory = customCacheDirectory\n//            } /*else {\n//                // If it doesn't we need to reset that preference\n//                preferences.customCacheDirectory = nil\n//            }*/\n//        }\n//\n//        if cacheDirectory == nil {\n//            let userCachePaths = NSSearchPathForDirectoriesInDomains(.cachesDirectory,\n//                                                                 .userDomainMask,\n//                                                                 true)\n//            let localCachePaths = NSSearchPathForDirectoriesInDomains(.cachesDirectory,\n//                                                                      .localDomainMask,\n//                                                                      true)\n//\n//            if !localCachePaths.isEmpty {\n//                let localCacheDirectory = localCachePaths[0] as NSString\n//                if aerialFolderExists(at: localCacheDirectory) {\n//                    debugLog(\"Using existing local cache /Library/Caches/Aerial\")\n//                    cacheDirectory = localCacheDirectory.appendingPathComponent(\"Aerial\")\n//                }\n//            }\n//\n//            if !userCachePaths.isEmpty && cacheDirectory == nil {\n//                let userCacheDirectory = userCachePaths[0] as NSString\n//\n//                if aerialFolderExists(at: userCacheDirectory) {\n//                    debugLog(\"Using existing user cache ~/Library/Caches/Aerial\")\n//                    cacheDirectory = userCacheDirectory.appendingPathComponent(\"Aerial\")\n//                } else {\n//                    debugLog(\"No local or user cache exists, using ~/Library/Application Support/Aerial\")\n//                    cacheDirectory = appSupportDirectory\n//                }\n//            }\n//        }\n//\n//        // Cache the computed value\n//        computedCacheDirectory = cacheDirectory\n//\n//        debugLog(\"cache to be used : \\(String(describing: cacheDirectory))\")\n//        return cacheDirectory\n    }\n\n    // MARK: - Helpers\n    static func aerialFolderExists(at: NSString) -> Bool {\n        let aerialFolder = at.appendingPathComponent(\"Aerial\")\n        if FileManager.default.fileExists(atPath: aerialFolder as String) {\n            return true\n        } else {\n            return false\n        }\n    }\n\n    // Is a video cached (in either appSupport or cache)\n    static func isAvailableOffline(video: AerialVideo) -> Bool {\n        let fileManager = FileManager.default\n\n        if video.url.absoluteString.starts(with: \"file\") {\n            return fileManager.fileExists(atPath: video.url.path)\n        } else {\n            if video.source.isCachable {\n                guard let videoCachePath = cachePath(forVideo: video) else {\n                    errorLog(\"Couldn't get video cache path!\")\n                    return false\n                }\n\n                if fileManager.fileExists(atPath: videoCachePath) {\n                    do {\n                        let fileUrl = Foundation.URL(fileURLWithPath: videoCachePath)\n                        \n                        \n                        let resourceValues = try fileUrl.resourceValues(forKeys: [.fileSizeKey])\n                        let fileSize = resourceValues.fileSize!\n\n                        // Make sure the file is big enough to be a video and not some network failure\n                        if fileSize > 500000 {\n                            return true\n                        }\n\n                    } catch {\n                        errorLog(\"File check throw\")\n                    }\n                }\n\n                return false\n            } else {\n                let path = sourcePathFor(video)\n                do {\n                    let fileUrl = Foundation.URL(fileURLWithPath: path)\n                    let resourceValues = try fileUrl.resourceValues(forKeys: [.fileSizeKey])\n                    let fileSize = resourceValues.fileSize!\n\n                    // Make sure the file is big enough to be a video and not some network failure\n                    if fileSize > 500000 {\n                        return true\n                    }\n\n                } catch {\n                    errorLog(\"File check throw\")\n                }\n                return false\n            }\n        }\n    }\n\n    static func moveToTrash(video: AerialVideo) {\n        let videoCachePath = VideoList.instance.localPathFor(video: video)\n\n        guard videoCachePath != \"\" else {\n            errorLog(\"Couldn't get video cache path to trash!\")\n            return\n        }\n\n        let vurl = Foundation.URL(fileURLWithPath: videoCachePath as String)\n        debugLog(\"trashing \\(vurl))\")\n        do {\n            try FileManager.default.trashItem(at: vurl, resultingItemURL: nil)\n        } catch let error {\n            errorLog(\"Could not move  \\(video.url) to trash \\(error)\")\n        }\n    }\n\n    static func cachePath(forVideo video: AerialVideo) -> String? {\n        if video.url.absoluteString.starts(with: \"file\") {\n            return video.url.path\n        }\n\n        let vurl = video.url\n        let filename = vurl.lastPathComponent\n        return cachePath(forFilename: filename)\n    }\n\n    static func cachePath(forFilename filename: String) -> String? {\n        guard let cacheDirectory = VideoCache.cacheDirectory, let appSupportDirectory = VideoCache.appSupportDirectory else {\n            return nil\n        }\n\n        // Let's compute both\n        let appSupportPath = appSupportDirectory as NSString\n        let appSupportVideoPath = appSupportPath.appendingPathComponent(filename)\n\n        let cacheDirectoryPath = cacheDirectory as NSString\n        let cacheVideoPath = cacheDirectoryPath.appendingPathComponent(filename)\n\n        // If the file exists in either dir, returns that\n        if FileManager.default.fileExists(atPath: appSupportVideoPath as String) {\n            return appSupportVideoPath\n        } else if FileManager.default.fileExists(atPath: cacheVideoPath as String) {\n            return cacheVideoPath\n        } else {\n            // File doesn't have to exist, this is also used to compute the save location\n            // So now with Catalina, considering containerization we need to use appSupport\n            // Pre catalina we return cache folder instead (no change for users)\n            return cacheVideoPath\n            /*\n            if #available(OSX 10.15, *) {\n                return appSupportVideoPath\n            } else {\n                return cacheVideoPath\n            }\n             */\n        }\n    }\n\n    static func sourcePathFor(_ video: AerialVideo) -> String {\n        if video.url.isFileURL {\n            return video.url.path\n        } else {\n            return Cache.supportPath.appending(\"/\" + video.source.name + \"/\" + video.url.lastPathComponent)\n        }\n    }\n\n    static func sourcePathFor(_ filename: String, video: AerialVideo) -> String {\n        return Cache.supportPath.appending(\"/\" + video.source.name + \"/\" + filename)\n    }\n\n    init(URL: Foundation.URL) {\n        debugLog(\"initvideocache\")\n        videoData = Data()\n        loading = true\n        self.URL = URL\n        loadCachedVideoIfPossible()\n    }\n\n    // MARK: - Data Adding\n\n    func receivedContentLength(_ contentLength: Int) {\n        if loading == false {\n            return\n        }\n\n        if mutableVideoData != nil {\n            return\n        }\n\n        mutableVideoData = NSMutableData(length: contentLength)\n        videoData = mutableVideoData! as Data\n    }\n\n    func receivedData(_ data: Data, atRange range: NSRange) {\n        guard let mutableVideoData = mutableVideoData else {\n            errorLog(\"Received data without having mutable video data\")\n            return\n        }\n\n        mutableVideoData.replaceBytes(in: range, withBytes: (data as NSData).bytes)\n        loadedRanges.append(range)\n\n        consolidateLoadedRanges()\n\n//        debugLog(\"loaded ranges: \\(loadedRanges)\")\n        if loadedRanges.count == 1 {\n            let range = loadedRanges[0]\n//            debugLog(\"checking if range \\(range) matches length \\(mutableVideoData.length)\")\n            if range.location == 0 && range.length == mutableVideoData.length {\n                // done loading, save\n                saveCachedVideo()\n            }\n        }\n    }\n\n    // MARK: - Save / Load Cache\n\n    var videoCachePath: String? {\n        let filename = URL.lastPathComponent\n\n        if let video = VideoList.instance.videoForFilename(filename) {\n            if !video.source.isCachable {\n                return VideoCache.sourcePathFor(filename, video: video)\n            }\n        }\n\n        return VideoCache.cachePath(forFilename: filename)\n    }\n\n    func saveCachedVideo() {\n        let fileManager = FileManager.default\n\n        guard let videoCachePath = videoCachePath else {\n            errorLog(\"Couldn't save cache file\")\n            return\n        }\n\n        guard fileManager.fileExists(atPath: videoCachePath) == false else {\n            errorLog(\"Cache file \\(videoCachePath) already exists.\")\n            return\n        }\n\n        loading = false\n        if mutableVideoData == nil {\n            errorLog(\"Missing video data for save.\")\n            return\n        }\n\n        do {\n            try mutableVideoData!.write(toFile: videoCachePath, options: .atomicWrite)\n\n            mutableVideoData = nil\n            videoData.removeAll()\n        } catch let error {\n            errorLog(\"Couldn't write cache file: \\(error)\")\n        }\n    }\n\n    func loadCachedVideoIfPossible() {\n        let fileManager = FileManager.default\n\n        guard let videoCachePath = self.videoCachePath else {\n            errorLog(\"Couldn't load cache file.\")\n            return\n        }\n\n        if fileManager.fileExists(atPath: videoCachePath) == false {\n            return\n        }\n\n        guard let videoData = try? Data(contentsOf: Foundation.URL(fileURLWithPath: videoCachePath)) else {\n            errorLog(\"NSData failed to load cache file \\(videoCachePath)\")\n            return\n        }\n\n        self.videoData = videoData\n        loading = false\n        debugLog(\"cached video file with length: \\(self.videoData.count)\")\n    }\n\n    // MARK: - Fulfilling cache\n\n    func fulfillLoadingRequest(_ loadingRequest: AVAssetResourceLoadingRequest) -> Bool {\n        guard let dataRequest = loadingRequest.dataRequest else {\n            errorLog(\"Missing data request for \\(loadingRequest)\")\n            return false\n        }\n\n        let requestedOffset = Int(dataRequest.requestedOffset)\n        let requestedLength = Int(dataRequest.requestedLength)\n\n        let data = videoData.subdata(in: requestedOffset..<requestedOffset + requestedLength)\n\n        DispatchQueue.main.async { () -> Void in\n            self.fillInContentInformation(loadingRequest)\n\n            dataRequest.respond(with: data)\n            loadingRequest.finishLoading()\n        }\n\n        return true\n    }\n\n    func fillInContentInformation(_ loadingRequest: AVAssetResourceLoadingRequest) {\n\n        guard let contentInformationRequest = loadingRequest.contentInformationRequest else {\n            return\n        }\n\n        let contentType: String = kUTTypeQuickTimeMovie as String\n\n        contentInformationRequest.isByteRangeAccessSupported = true\n        contentInformationRequest.contentType = contentType\n        contentInformationRequest.contentLength = Int64(videoData.count)\n    }\n\n    // MARK: - Cache Checking\n\n    // Whether the video cache can fulfill this request\n    func canFulfillLoadingRequest(_ loadingRequest: AVAssetResourceLoadingRequest) -> Bool {\n\n        if !loading {\n            return true\n        }\n\n        guard let dataRequest = loadingRequest.dataRequest else {\n            errorLog(\"Missing data request for \\(loadingRequest)\")\n            return false\n        }\n\n        let requestedOffset = Int(dataRequest.requestedOffset)\n        let requestedLength = Int(dataRequest.requestedLength)\n        let requestedEnd = requestedOffset + requestedLength\n\n        for range in loadedRanges {\n            let rangeStart = range.location\n            let rangeEnd = range.location + range.length\n\n            if requestedOffset >= rangeStart && requestedEnd <= rangeEnd {\n                return true\n            }\n        }\n\n        return false\n    }\n\n    // MARK: - Consolidating\n\n    func consolidateLoadedRanges() {\n        var consolidatedRanges: [NSRange] = []\n\n        let sortedRanges = loadedRanges.sorted { $0.location < $1.location }\n\n        var previousRange: NSRange?\n        var lastIndex: Int?\n        for range in sortedRanges {\n            if let lastRange: NSRange = previousRange {\n                let lastRangeEndOffset = lastRange.location + lastRange.length\n\n                // check if range can be consumed by lastRange\n                // or if they're at each other's edges if it can be merged\n\n                if lastRangeEndOffset >= range.location {\n                    let endOffset = range.location + range.length\n\n                    // check if this range's end offset is larger than lastRange's\n                    if endOffset > lastRangeEndOffset {\n                        previousRange!.length = endOffset - lastRange.location\n\n                        // replace lastRange in array with new value\n                        consolidatedRanges.remove(at: lastIndex!)\n                        consolidatedRanges.append(previousRange!)\n                        continue\n                    } else {\n                        // skip adding this to the array, previous range is already bigger\n//                        debugLog(\"skipping add of \\(range), previous: \\(previousRange)\")\n                        continue\n                    }\n                }\n            }\n\n            lastIndex = consolidatedRanges.count\n            previousRange = range\n            consolidatedRanges.append(range)\n        }\n        loadedRanges = consolidatedRanges\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Models/Cache/VideoDownload.swift",
    "content": "//\n//  VideoDownload.swift\n//  Aerial\n//\n//  Created by John Coates on 10/31/15.\n//  Copyright © 2015 John Coates. All rights reserved.\n//\n\nimport Foundation\n\nprotocol VideoDownloadDelegate: NSObjectProtocol {\n    func videoDownload(_ videoDownload: VideoDownload,\n                       finished success: Bool, errorMessage: String?)\n    // bytes received for bytes/second count\n    func videoDownload(_ videoDownload: VideoDownload,\n                       receivedBytes: Int, progress: Float)\n}\n\nfinal class VideoDownloadStream {\n    var connection: NSURLConnection\n    var response: URLResponse?\n    var contentInformationRequest: Bool = false\n    var downloadOffset = 0\n\n    init(connection: NSURLConnection) {\n        self.connection = connection\n    }\n    deinit {\n        connection.cancel()\n    }\n}\n\nfinal class VideoDownload: NSObject, NSURLConnectionDataDelegate {\n    var streams: [VideoDownloadStream] = []\n    weak var delegate: VideoDownloadDelegate!\n\n    let queue = DispatchQueue.main\n\n    let video: AerialVideo\n\n    var data: NSMutableData?\n    var downloadedData: Int = 0\n    var contentLength: Int = 0\n\n    init(video: AerialVideo, delegate: VideoDownloadDelegate) {\n        self.video = video\n        self.delegate = delegate\n    }\n\n    deinit {\n        //print(\"deinit VideoDownload\")\n    }\n\n    func startDownload() {\n        // first start content information download\n        startDownloadForContentInformation()\n    }\n\n    // download a couple bytes to get the content length\n    func startDownloadForContentInformation() {\n        startDownloadForChunk(nil)\n    }\n\n    func cancel() {\n        for stream in streams {\n            stream.connection.cancel()\n        }\n        infoLog(\"Video download cancelled\")\n        delegate.videoDownload(self, finished: false, errorMessage: nil)\n    }\n\n    func startDownloadForChunk(_ chunk: NSRange?) {\n        let request = NSMutableURLRequest(url: video.url as URL)\n        request.cachePolicy = NSURLRequest.CachePolicy.reloadIgnoringCacheData\n\n        if let requestedRange = chunk {\n            // set Range: bytes=startOffset-endOffset\n            let requestRangeField = \"bytes=\\(requestedRange.location)-\\(requestedRange.location+requestedRange.length)\"\n            request.setValue(requestRangeField, forHTTPHeaderField: \"Range\")\n            debugLog(\"Starting download for range \\(requestRangeField)\")\n        }\n\n        guard let connection = NSURLConnection(request: request as URLRequest,\n                                               delegate: self, startImmediately: false) else {\n            errorLog(\"Error creating connection with request: \\(request)\")\n            return\n        }\n\n        let stream = VideoDownloadStream(connection: connection)\n\n        if chunk == nil {\n            debugLog(\"Starting download for content information\")\n            stream.contentInformationRequest = true\n        }\n\n        connection.start()\n\n        streams.append(stream)\n\n    }\n\n    func streamForConnection(_ connection: NSURLConnection) -> VideoDownloadStream? {\n        return streams.first(where: { $0.connection == connection })\n    }\n\n    func createStreamsBasedOnContentLength(_ contentLength: Int) {\n        self.contentLength = contentLength\n        // remove content length request stream\n        streams.removeFirst()\n\n        data = NSMutableData(length: contentLength)\n\n        // start 4 streams for maximum throughput\n        let streamCount = 1 // TODO\n        let pace = 0.2; // pace stream creation a little bit\n        let streamPiece = Int(floor(Double(contentLength) / Double(streamCount)))\n        debugLog(\"Starting \\(streamCount) streams with \\(streamPiece) each, for content length of \\(contentLength)\")\n        var offset = 0\n\n        var delayTime: Double = 0\n\n//        let queue = DispatchQueue.main\n        for idx in 0 ..< streamCount {\n            let isLastStream: Bool = idx == (streamCount - 1)\n            var range = NSRange(location: offset, length: streamPiece)\n\n            if isLastStream {\n                let bytesLeft = contentLength - offset\n                range = NSRange(location: offset, length: bytesLeft)\n                debugLog(\"last stream range: \\(range)\")\n            }\n\n            let delay = DispatchTime.now() + Double(Int64(delayTime * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)\n            queue.asyncAfter(deadline: delay) {\n                self.startDownloadForChunk(range)\n            }\n\n            // increase delay\n            delayTime += pace\n\n            // increase offset\n            offset += range.length\n        }\n    }\n\n    func receiveDataForStream(_ stream: VideoDownloadStream, receivedData: Data) {\n        guard let videoData = self.data else {\n            errorLog(\"Aerial error: video data missing!\")\n            return\n        }\n\n        let replaceRange = NSRange(location: stream.downloadOffset,\n                                   length: receivedData.count)\n        videoData.replaceBytes(in: replaceRange, withBytes: (receivedData as NSData).bytes)\n        stream.downloadOffset += receivedData.count\n    }\n\n    func finishedDownload() {\n        var tentativeCachePath: String?\n\n        if video.source.isCachable {\n            tentativeCachePath = VideoCache.cachePath(forVideo: video)\n        } else {\n            tentativeCachePath = VideoCache.sourcePathFor(video)\n        }\n\n        guard let videoCachePath = tentativeCachePath else {\n            errorLog(\"Couldn't save video because couldn't get cache path\\n\")\n            failedDownload(\"Couldn't get cache path\")\n            return\n        }\n\n        if self.data == nil {\n            errorLog(\"video data missing!\\n\")\n            return\n        }\n\n        var success: Bool = true\n        var errorMessage: String?\n        do {\n            try self.data!.write(toFile: videoCachePath, options: .atomicWrite)\n\n            self.data = nil\n        } catch let error {\n            errorLog(\"Couldn't write cache file: \\(error)\")\n            errorMessage = \"Couldn't write to cache file!\"\n            success = false\n        }\n\n        // notify delegate\n        delegate.videoDownload(self, finished: success, errorMessage: errorMessage)\n    }\n\n    func failedDownload(_ errorMessage: String) {\n\n        delegate.videoDownload(self, finished: false, errorMessage: errorMessage)\n    }\n\n    // MARK: - NSURLConnection Delegate\n\n    func connection(_ connection: NSURLConnection, didReceive response: URLResponse) {\n        guard let stream = streamForConnection(connection) else {\n            errorLog(\"No matching stream for connection: \\(connection) with response: \\(response)\")\n            return\n        }\n\n        stream.response = response as? HTTPURLResponse\n\n        if stream.contentInformationRequest == true {\n            connection.cancel()\n\n            queue.async(execute: { () -> Void in\n                let contentLength = Int(response.expectedContentLength)\n                self.createStreamsBasedOnContentLength(contentLength)\n            })\n\n            return\n        } else {\n            // get real offset of receiving data\n\n            queue.async(execute: { () -> Void in\n                guard let offset = self.startOffsetFromResponse(response) else {\n                    errorLog(\"Couldn't get start offset from response: \\(response)\")\n                    return\n                }\n\n                stream.downloadOffset = offset\n            })\n        }\n    }\n\n    func connection(_ connection: NSURLConnection, didReceive data: Data) {\n        guard let delegate = self.delegate else {\n            return\n        }\n\n        queue.async { () -> Void in\n            self.downloadedData += data.count\n            let progress: Float = Float(self.downloadedData) / Float(self.contentLength)\n            delegate.videoDownload(self, receivedBytes: data.count, progress: progress)\n\n            guard let stream = self.streamForConnection(connection) else {\n                errorLog(\"No matching stream for connection: \\(connection)\")\n                return\n            }\n\n            self.receiveDataForStream(stream, receivedData: data)\n        }\n    }\n\n    func connectionDidFinishLoading(_ connection: NSURLConnection) {\n        queue.async { () -> Void in\n            debugLog(\"connectionDidFinishLoading\")\n\n            guard let stream = self.streamForConnection(connection) else {\n                errorLog(\"No matching stream for connection: \\(connection)\")\n                return\n            }\n\n            guard let index = self.streams.firstIndex(where: { $0.connection == stream.connection }) else {\n                errorLog(\"Couldn't find index of stream for finished connection!\")\n                return\n            }\n\n            self.streams.remove(at: index)\n\n            if self.streams.isEmpty {\n                debugLog(\"Finished downloading!\")\n                self.finishedDownload()\n            }\n        }\n    }\n\n    func connection(_ connection: NSURLConnection, didFailWithError error: Error) {\n        errorLog(\"Couldn't download video: \\(error.localizedDescription)\")\n        queue.async { () -> Void in\n            self.failedDownload(\"Connection fail: \\(error.localizedDescription)\")\n        }\n    }\n\n    func connection(_ connection: NSURLConnection, didReceive challenge: URLAuthenticationChallenge) {\n        errorLog(\"Didn't expect authentication challenge while downloading videos!\")\n        queue.async { () -> Void in\n            self.failedDownload(\"Connection fail: Received authentication request!\")\n        }\n    }\n\n    // MARK: - Range\n    func startOffsetFromResponse(_ response: URLResponse) -> Int? {\n        // get range response\n        var regex: NSRegularExpression!\n        do {\n            // Check to see if the server returned a valid byte-range\n            regex = try NSRegularExpression(pattern: \"bytes (\\\\d+)-\\\\d+/\\\\d+\",\n                                            options: NSRegularExpression.Options.caseInsensitive)\n        } catch let error as NSError {\n            errorLog(\"Error formatting regex: \\(error)\")\n            return nil\n        }\n\n        let httpResponse = response as! HTTPURLResponse\n\n        guard let contentRange = httpResponse.allHeaderFields[\"Content-Range\"] as? NSString else {\n            errorLog(\"Weird, no byte response: \\(response)\")\n            return nil\n        }\n\n        guard let match = regex.firstMatch(in: contentRange as String,\n                                           options: NSRegularExpression.MatchingOptions.anchored,\n                                           range: NSRange(location: 0, length: contentRange.length)) else {\n            errorLog(\"Weird, couldn't make a regex match for byte offset: \\(contentRange)\")\n            return nil\n        }\n        let offsetMatchRange = match.range(at: 1)\n        let offsetString = contentRange.substring(with: offsetMatchRange) as NSString\n\n        let offset = offsetString.longLongValue\n\n        return Int(offset)\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Models/Cache/VideoLoader.swift",
    "content": "//\n//  VideoLoader.swift\n//  Aerial\n//\n//  Created by John Coates on 10/29/15.\n//  Copyright © 2015 John Coates. All rights reserved.\n//\n\nimport Foundation\nimport AVFoundation\n\nprotocol VideoLoaderDelegate: NSObjectProtocol {\n    func videoLoader(_ videoLoader: VideoLoader, receivedResponse response: URLResponse)\n    func videoLoader(_ videoLoader: VideoLoader, receivedData data: Data, forRange range: NSRange)\n}\n\nfinal class VideoLoader: NSObject, NSURLConnectionDataDelegate {\n    var connection: NSURLConnection?\n    var response: HTTPURLResponse?\n    weak var delegate: VideoLoaderDelegate?\n    var loadingRequest: AVAssetResourceLoadingRequest\n\n    // range params\n    var loadedRange: NSRange\n    var requestedRange: NSRange\n    var loadRange: Bool\n\n    let queue = DispatchQueue.main\n\n    init(url: URL, loadingRequest: AVAssetResourceLoadingRequest, delegate: VideoLoaderDelegate) {\n        // debugLog(\"videoloader init\")\n        self.delegate = delegate\n        self.loadingRequest = loadingRequest\n\n        let request = NSMutableURLRequest(url: url)\n        request.cachePolicy = NSURLRequest.CachePolicy.reloadIgnoringLocalCacheData\n\n        loadRange = false\n        loadedRange = NSRange(location: 0, length: 0)\n        requestedRange = NSRange(location: 0, length: 0)\n\n        if let dataRequest = loadingRequest.dataRequest {\n            if dataRequest.requestedOffset > 0 {\n                loadRange = true\n                let startOffset = Int(dataRequest.requestedOffset)\n                let requestedBytes = Int(dataRequest.requestedLength)\n                loadedRange = NSRange(location: startOffset, length: 0)\n                requestedRange = NSRange(location: startOffset, length: requestedBytes)\n\n                // set Range: bytes=startOffset-endOffset\n                let requestRange = \"bytes=\\(requestedRange.location)-\\(requestedRange.location+requestedRange.length)\"\n                request.setValue(requestRange, forHTTPHeaderField: \"Range\")\n            }\n        }\n\n        super.init()\n\n        connection = NSURLConnection(request: request as URLRequest, delegate: self, startImmediately: false)\n\n        guard let connection = connection else {\n            errorLog(\"Couldn't instantiate connection.\")\n            return\n        }\n\n        connection.setDelegateQueue(OperationQueue.main)\n        loadedRange = NSRange(location: requestedRange.location, length: 0)\n\n        connection.start()\n        // debugLog(\"Starting request: \\(request)\")\n    }\n\n    deinit {\n        connection?.cancel()\n    }\n\n    // MARK: - NSURLConnection Delegate\n\n    func connection(_ connection: NSURLConnection, didReceive response: URLResponse) {\n\n        if loadRange {\n            if let startOffset = startOffsetFromResponse(response) {\n                loadedRange.location = startOffset\n            }\n        }\n\n        self.response = response as? HTTPURLResponse\n\n        queue.async { () -> Void in\n            self.delegate?.videoLoader(self, receivedResponse: response)\n            self.fillInContentInformation(self.loadingRequest)\n        }\n    }\n\n    func connection(_ connection: NSURLConnection, didReceive data: Data) {\n\n        queue.async { () -> Void in\n            self.fillInContentInformation(self.loadingRequest)\n\n            guard let dataRequest = self.loadingRequest.dataRequest else {\n                errorLog(\"Data request missing for \\(self.loadingRequest)\")\n                return\n            }\n\n            let requestedRange = self.requestedRange\n            let loadedRange = self.loadedRange\n            let loadedLocation = loadedRange.location + loadedRange.length\n\n            let dataRange = NSRange(location: loadedRange.location + loadedRange.length,\n                                    length: data.count)\n\n            self.delegate?.videoLoader(self, receivedData: data, forRange: dataRange)\n\n            // check if we've already been sending content, or we're at right byte offset\n            if loadedLocation >= requestedRange.location {\n                let requestedEndOffset = Int(dataRequest.requestedOffset + Int64(dataRequest.requestedLength))\n\n                let pendingDataEndOffset = loadedLocation + data.count\n                // debugLog(\"r \\(requestedEndOffset) p \\(pendingDataEndOffset)\")\n\n                if pendingDataEndOffset > requestedEndOffset {\n                    let truncateDataLength = pendingDataEndOffset - requestedEndOffset\n                    let truncatedData = data.subdata(in: 0..<data.count - truncateDataLength)\n                    dataRequest.respond(with: truncatedData)\n                    self.loadingRequest.finishLoading()\n                    self.connection?.cancel()\n                } else {\n                    // debugLog(\"rr\")\n                    dataRequest.respond(with: data)\n                }\n                // debugLog(\"Responding with data\")\n            }\n                // check if we're at a point now where we can send content\n            else if loadedLocation + data.count >= requestedRange.location {\n                // debugLog(\"case2\")\n                // calculate how far along we need to be into the data before it's part of what\n                // was requested\n                let inset = requestedRange.location - loadedRange.location\n\n                if inset > 0 {\n                    let start = inset\n                    let length = data.count - inset\n                    let end = start + length\n                    let responseData = data.subdata(in: inset..<end)\n                    dataRequest.respond(with: responseData)\n\n                    if dataRequest.currentOffset >= dataRequest.requestedOffset + Int64(dataRequest.requestedLength) {\n                        self.loadingRequest.finishLoading()\n                        self.connection?.cancel()\n                    }\n                } else if inset < 1 {\n                    errorLog(\"Inset is invalid value: \\(inset)\")\n                }\n\n            }\n\n            // debugLog(\"Received data with length: \\(data.count)\")\n\n            self.loadedRange.length += data.count\n\n        }\n    }\n\n    func connectionDidFinishLoading(_ connection: NSURLConnection) {\n\n        queue.async { () -> Void in\n            debugLog(\"connectionDidFinishLoading\")\n            self.loadingRequest.finishLoading()\n        }\n    }\n\n    func fillInContentInformation(_ loadingRequest: AVAssetResourceLoadingRequest) {\n\n        guard let contentInformationRequest = loadingRequest.contentInformationRequest else {\n            return\n        }\n\n        guard let response = self.response else {\n            debugLog(\"No response\")\n            return\n        }\n\n        guard let mimeType = response.mimeType else {\n            debugLog(\"no mimeType for \\(response)\")\n            return\n        }\n\n        guard let uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, mimeType as CFString, nil) else {\n            debugLog(\"couldn't create prefered identifier for tag \\(mimeType)\")\n            return\n        }\n\n        debugLog(\"Processsing contentInformationRequest\")\n\n        let contentType: String = uti.takeRetainedValue() as String\n\n        contentInformationRequest.isByteRangeAccessSupported = true\n        contentInformationRequest.contentType = contentType\n        contentInformationRequest.contentLength = response.expectedContentLength\n\n        debugLog(\"expected content length: \\(response.expectedContentLength) type:\\(contentType)\")\n    }\n\n    // MARK: - Range\n\n    func startOffsetFromResponse(_ response: URLResponse) -> Int? {\n\n        // get range response\n        var regex: NSRegularExpression!\n        do {\n            // Check to see if the server returned a valid byte-range\n            regex = try NSRegularExpression(pattern: \"bytes (\\\\d+)-\\\\d+/\\\\d+\",\n                                            options: NSRegularExpression.Options.caseInsensitive)\n        } catch let error as NSError {\n            errorLog(\"Error formatting regex: \\(error)\")\n            return nil\n        }\n\n        let httpResponse = response as! HTTPURLResponse\n\n        guard let contentRange = httpResponse.allHeaderFields[\"Content-Range\"] as? NSString else {\n            errorLog(\"Weird, no byte response: \\(response)\")\n            return nil\n        }\n\n        guard let match = regex.firstMatch(in: contentRange as String,\n                                           options: NSRegularExpression.MatchingOptions.anchored,\n                                           range: NSRange(location: 0, length: contentRange.length)) else {\n            errorLog(\"Weird, couldn't make a regex match for byte offset: \\(contentRange)\")\n            return nil\n        }\n        let offsetMatchRange = match.range(at: 1)\n        let offsetString = contentRange.substring(with: offsetMatchRange) as NSString\n\n        let offset = offsetString.longLongValue\n\n        // debugLog(\"content range: \\(contentRange), start offset: \\(offset)\")\n\n        return Int(offset)\n    }\n\n}\n"
  },
  {
    "path": "Aerial/Source/Models/Cache/VideoManager.swift",
    "content": "//\n//  VideoManager.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 08/10/2018.\n//  Copyright © 2018 John Coates. All rights reserved.\n//\n\nimport Foundation\ntypealias VideoManagerCallback = (Int, Int) -> Void\ntypealias VideoProgressCallback = (Int, Int, Double) -> Void\n\nfinal class VideoManager: NSObject {\n    static let sharedInstance = VideoManager()\n    var managerCallbacks = [VideoManagerCallback]()\n    var progressCallbacks = [VideoProgressCallback]()\n\n    /// Dictionary of CheckCellView, keyed by the video.id\n    private var checkCells = [String: CheckCellView]()\n\n    /// List of queued videos, by video.id\n    private var queuedVideos = [String]()\n\n    /// Dictionary of operations, keyed by the video.id\n    fileprivate var operations = [String: VideoDownloadOperation]()\n\n    /// Number of videos that were queued\n    private var totalQueued = 0\n    var stopAll = false\n\n    // var downloadItems: [VideoDownloadItem]\n    /// Serial OperationQueue for downloads\n\n    private let queue: OperationQueue = {\n        // swiftlint:disable:next identifier_name\n        let _queue = OperationQueue()\n        _queue.name = \"videodownload\"\n        _queue.maxConcurrentOperationCount = 1\n\n        return _queue\n    }()\n\n    // MARK: Tracking CheckCellView\n    func addCheckCellView(id: String, checkCellView: CheckCellView) {\n        checkCells[id] = checkCellView\n    }\n\n    func addCallback(_ callback:@escaping VideoManagerCallback) {\n        managerCallbacks.append(callback)\n    }\n\n    func addProgressCallback(_ callback:@escaping VideoProgressCallback) {\n        progressCallbacks.append(callback)\n    }\n\n    func updateAllCheckCellView() {\n        for view in checkCells {\n            view.value.adaptIndicators()\n        }\n    }\n\n    // Is the video queued for download ?\n    func isVideoQueued(id: String) -> Bool {\n        if queuedVideos.firstIndex(of: id) != nil {\n            return true\n        } else {\n            return false\n        }\n    }\n\n    @discardableResult\n    func queueDownload(_ video: AerialVideo) -> VideoDownloadOperation {\n        if stopAll {\n            stopAll = false\n        }\n\n        let operation = VideoDownloadOperation(video: video, delegate: self)\n        operations[video.id] = operation\n        queue.addOperation(operation)\n\n        queuedVideos.append(video.id)       // Our Internal List of queued videos\n        markAsQueued(id: video.id)          // Callback the CheckCellView\n        totalQueued += 1                    // Increment our count\n\n        DispatchQueue.main.async {\n            // Callback the callbacks\n            for callback in self.managerCallbacks {\n                callback(self.totalQueued-self.queuedVideos.count, self.totalQueued)\n            }\n        }\n        return operation\n    }\n\n    // Callbacks for Items\n    func finishedDownload(id: String, success: Bool) {\n        // Manage our queuedVideo index\n        if let index = queuedVideos.firstIndex(of: id) {\n            queuedVideos.remove(at: index)\n        }\n\n        if queuedVideos.isEmpty {\n            totalQueued = 0\n        }\n\n        DispatchQueue.main.async {\n            // Callback the callbacks\n            for callback in self.managerCallbacks {\n                callback(self.totalQueued-self.queuedVideos.count, self.totalQueued)\n            }\n        }\n        // Then callback the CheckCellView\n        if let cell = checkCells[id] {\n            if success {\n                cell.markAsDownloaded()\n            } else {\n                cell.markAsNotDownloaded()\n            }\n        }\n    }\n\n    func markAsQueued(id: String) {\n        // Manage our queuedVideo index\n        if let cell = checkCells[id] {\n            cell.markAsQueued()\n        }\n    }\n    func updateProgress(id: String, progress: Double) {\n        if let cell = checkCells[id] {\n            cell.updateProgressIndicator(progress: progress)\n        }\n        DispatchQueue.main.async {\n            // Callback the callbacks\n            for callback in self.progressCallbacks {\n                callback(self.totalQueued-self.queuedVideos.count, self.totalQueued, progress)\n            }\n        }\n    }\n\n    /// Cancel all queued operations\n\n    func cancelAll() {\n        stopAll = true\n        queue.cancelAllOperations()\n    }\n}\n\nfinal class VideoDownloadOperation: AsynchronousOperation {\n    var video: AerialVideo\n    var download: VideoDownload?\n\n    init(video: AerialVideo, delegate: VideoManager) {\n        debugLog(\"Video queued \\(video.name)\")\n        self.video = video\n    }\n\n    override func main() {\n        let videoManager = VideoManager.sharedInstance\n        if videoManager.stopAll {\n            return\n        }\n\n        debugLog(\"Starting download for \\(video.name)\")\n        DispatchQueue.main.async {\n            self.download = VideoDownload(video: self.video, delegate: self)\n            self.download!.startDownload()\n        }\n    }\n\n    override func cancel() {\n        defer { finish() }\n        let videoManager = VideoManager.sharedInstance\n\n        if let _ = self.download {\n            self.download!.cancel()\n        } else {\n            videoManager.finishedDownload(id: self.video.id, success: false)\n        }\n        self.download = nil\n        super.cancel()\n        // finish()\n    }\n}\n\nextension VideoDownloadOperation: VideoDownloadDelegate {\n    func videoDownload(_ videoDownload: VideoDownload,\n                       finished success: Bool, errorMessage: String?) {\n        debugLog(\"Finished\")\n        defer { finish() }\n\n        let videoManager = VideoManager.sharedInstance\n        if success {\n            // Call up to clean the view\n            videoManager.finishedDownload(id: videoDownload.video.id, success: true)\n        } else {\n            if let _ = errorMessage {\n                errorLog(errorMessage!)\n            }\n\n            videoManager.finishedDownload(id: videoDownload.video.id, success: false)\n        }\n    }\n\n    func videoDownload(_ videoDownload: VideoDownload, receivedBytes: Int, progress: Float) {\n        // Call up to update the view\n        let videoManager = VideoManager.sharedInstance\n        videoManager.updateProgress(id: videoDownload.video.id, progress: Double(progress))\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Models/CompanionBridge.swift",
    "content": "//\n//  CompanionBridge.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 09/10/2023.\n//  Copyright © 2023 Guillaume Louel. All rights reserved.\n//\n// This acts as our bridge to Companion when the plugin needs data FROM companion\n// Currently using DistributedNotificationCenter, until *that* breaks too...\n\nimport Foundation\n\nstruct CompanionBridge {\n    static var nightShiftSunrise: Date?\n    static var nightShiftSunset: Date?\n    \n    static var locationLat: Double?\n    static var locationLong: Double?\n    \n    static func setNotifications() {\n        debugLog(\"🌉 seting up CompanionBridge\")\n\n        // Get nightshift\n        DistributedNotificationCenter.default().addObserver(forName: NSNotification.Name(\"com.glouel.aerial.nightshift\"), object: nil, queue: nil) { notification in\n            debugLog(\"🌉😻 received nightshift\")\n            debugLog(notification.debugDescription)\n            \n            if let sunrise = notification.userInfo?[\"sunrise\"] as? Date {\n                debugLog(\"parsed sunrise\")\n                nightShiftSunrise = sunrise\n            } else {\n                debugLog(\"can't parse sunrise\")\n            }\n\n            if let sunset = notification.userInfo?[\"sunset\"] as? Date {\n                debugLog(\"parsed sunset\")\n                nightShiftSunset = sunset\n            }\n        }\n\n        // Get location\n        DistributedNotificationCenter.default().addObserver(forName: NSNotification.Name(\"com.glouel.aerial.location\"), object: nil, queue: nil) { notification in\n            debugLog(\"🌉😻 received location\")\n            debugLog(notification.debugDescription)\n            \n            if let lat = notification.userInfo?[\"latitude\"] as? Double {\n                debugLog(\"parsed latitude\")\n                locationLat = lat\n            } else {\n                debugLog(\"can't parse latitude\")\n            }\n\n            if let long = notification.userInfo?[\"longitude\"] as? Double {\n                debugLog(\"parsed longitude\")\n                locationLong = long\n            }\n        }\n        \n        \n        // Test request\n        DistributedNotificationCenter.default().postNotificationName(NSNotification.Name(\"com.glouel.aerial.getnightshift\"), object: nil, deliverImmediately: true)\n        \n        if PrefsInfo.weather.locationMode == .useCurrent || PrefsTime.timeMode == .locationService {\n            debugLog(\"🌉 asking for location\")\n            DistributedNotificationCenter.default().postNotificationName(NSNotification.Name(\"com.glouel.aerial.getlocation\"), object: nil, deliverImmediately: true)\n        }\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Models/CustomVideoFolders+helpers.swift",
    "content": "//\n//  CustomVideoFolders+helpers.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 24/05/2019.\n//  Copyright © 2019 John Coates. All rights reserved.\n//\n\nimport Foundation\n\n// Helpers added on top of our generated json class\nextension CustomVideoFolders {\n    func hasFolder(withUrl: String) -> Bool {\n        for folder in folders where folder.url == withUrl {\n            return true\n        }\n\n        return false\n    }\n\n    func getFolderIndex(withUrl: String) -> Int {\n        var index = 0\n        for folder in folders {\n            if folder.url == withUrl {\n                return index\n            }\n            index += 1\n        }\n        return -1\n    }\n\n    func getFolder(withUrl: String) -> Folder? {\n        for folder in folders where folder.url == withUrl {\n            return folder\n        }\n\n        return nil\n    }\n}\n\nextension Folder {\n    func hasAsset(withUrl: String) -> Bool {\n        for asset in assets where asset.url == withUrl {\n            return true\n        }\n        return false\n    }\n\n    func getAssetIndex(withUrl: String) -> Int {\n        var index = 0\n        for asset in assets {\n            if asset.url == withUrl {\n                return index\n            }\n            index += 1\n        }\n        return -1\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Models/CustomVideoFolders.swift",
    "content": "// This file was generated from JSON Schema using quicktype, do not modify it directly.\n// To parse the JSON, add this file to your project and do:\n//\n//   let customVideoFolders = try CustomVideoFolders(json)\n\nimport Foundation\n\n// MARK: - CustomVideoFolders\nclass CustomVideoFolders: Codable {\n    var folders: [Folder]\n\n    enum CodingKeys: String, CodingKey {\n        case folders = \"folders\"\n    }\n\n    init(folders: [Folder]) {\n        self.folders = folders\n    }\n}\n\n// MARK: CustomVideoFolders convenience initializers and mutators\n\nextension CustomVideoFolders {\n    convenience init(data: Data) throws {\n        let me = try newJSONDecoder().decode(CustomVideoFolders.self, from: data)\n        self.init(folders: me.folders)\n    }\n\n    convenience init(_ json: String, using encoding: String.Encoding = .utf8) throws {\n        guard let data = json.data(using: encoding) else {\n            throw NSError(domain: \"JSONDecoding\", code: 0, userInfo: nil)\n        }\n        try self.init(data: data)\n    }\n\n    convenience init(fromURL url: URL) throws {\n        try self.init(data: try Data(contentsOf: url))\n    }\n\n    func with(\n        folders: [Folder]? = nil\n        ) -> CustomVideoFolders {\n        return CustomVideoFolders(\n            folders: folders ?? self.folders\n        )\n    }\n\n    func jsonData() throws -> Data {\n        return try newJSONEncoder().encode(self)\n    }\n\n    func jsonString(encoding: String.Encoding = .utf8) throws -> String? {\n        return String(data: try self.jsonData(), encoding: encoding)\n    }\n}\n\n// MARK: - Folder\nclass Folder: Codable {\n    var url: String\n    var label: String\n    var assets: [Asset]\n\n    enum CodingKeys: String, CodingKey {\n        case url = \"url\"\n        case label = \"label\"\n        case assets = \"assets\"\n    }\n\n    init(url: String, label: String, assets: [Asset]) {\n        self.url = url\n        self.label = label\n        self.assets = assets\n    }\n}\n\n// MARK: Folder convenience initializers and mutators\n\nextension Folder {\n    convenience init(data: Data) throws {\n        let me = try newJSONDecoder().decode(Folder.self, from: data)\n        self.init(url: me.url, label: me.label, assets: me.assets)\n    }\n\n    convenience init(_ json: String, using encoding: String.Encoding = .utf8) throws {\n        guard let data = json.data(using: encoding) else {\n            throw NSError(domain: \"JSONDecoding\", code: 0, userInfo: nil)\n        }\n        try self.init(data: data)\n    }\n\n    convenience init(fromURL url: URL) throws {\n        try self.init(data: try Data(contentsOf: url))\n    }\n\n    func with(\n        url: String? = nil,\n        label: String? = nil,\n        assets: [Asset]? = nil\n        ) -> Folder {\n        return Folder(\n            url: url ?? self.url,\n            label: label ?? self.label,\n            assets: assets ?? self.assets\n        )\n    }\n\n    func jsonData() throws -> Data {\n        return try newJSONEncoder().encode(self)\n    }\n\n    func jsonString(encoding: String.Encoding = .utf8) throws -> String? {\n        return String(data: try self.jsonData(), encoding: encoding)\n    }\n}\n\n// MARK: - Asset\nclass Asset: Codable {\n    var pointsOfInterest: [String: String]\n    var url: String\n    var accessibilityLabel: String\n    var id: String\n    var time: String\n\n    enum CodingKeys: String, CodingKey {\n        case pointsOfInterest = \"pointsOfInterest\"\n        case url = \"url\"\n        case accessibilityLabel = \"accessibilityLabel\"\n        case id = \"id\"\n        case time = \"time\"\n    }\n\n    init(pointsOfInterest: [String: String], url: String, accessibilityLabel: String, id: String, time: String) {\n        self.pointsOfInterest = pointsOfInterest\n        self.url = url\n        self.accessibilityLabel = accessibilityLabel\n        self.id = id\n        self.time = time\n    }\n}\n\n// MARK: Asset convenience initializers and mutators\n\nextension Asset {\n    convenience init(data: Data) throws {\n        let me = try newJSONDecoder().decode(Asset.self, from: data)\n        self.init(pointsOfInterest: me.pointsOfInterest, url: me.url, accessibilityLabel: me.accessibilityLabel, id: me.id, time: me.time)\n    }\n\n    convenience init(_ json: String, using encoding: String.Encoding = .utf8) throws {\n        guard let data = json.data(using: encoding) else {\n            throw NSError(domain: \"JSONDecoding\", code: 0, userInfo: nil)\n        }\n        try self.init(data: data)\n    }\n\n    convenience init(fromURL url: URL) throws {\n        try self.init(data: try Data(contentsOf: url))\n    }\n\n    func with(\n        pointsOfInterest: [String: String]? = nil,\n        url: String? = nil,\n        accessibilityLabel: String? = nil,\n        id: String? = nil,\n        time: String? = nil\n        ) -> Asset {\n        return Asset(\n            pointsOfInterest: pointsOfInterest ?? self.pointsOfInterest,\n            url: url ?? self.url,\n            accessibilityLabel: accessibilityLabel ?? self.accessibilityLabel,\n            id: id ?? self.id,\n            time: time ?? self.time\n        )\n    }\n\n    func jsonData() throws -> Data {\n        return try newJSONEncoder().encode(self)\n    }\n\n    func jsonString(encoding: String.Encoding = .utf8) throws -> String? {\n        return String(data: try self.jsonData(), encoding: encoding)\n    }\n}\n\n// MARK: - Helper functions for creating encoders and decoders\n\nfunc newJSONDecoder() -> JSONDecoder {\n    let decoder = JSONDecoder()\n    if #available(iOS 10.0, OSX 10.12, tvOS 10.0, watchOS 3.0, *) {\n        decoder.dateDecodingStrategy = .iso8601\n    }\n    return decoder\n}\n\nfunc newJSONEncoder() -> JSONEncoder {\n    let encoder = JSONEncoder()\n    encoder.outputFormatting = .prettyPrinted\n    if #available(iOS 10.0, OSX 10.12, tvOS 10.0, watchOS 3.0, *) {\n        encoder.dateEncodingStrategy = .iso8601\n    }\n    return encoder\n}\n"
  },
  {
    "path": "Aerial/Source/Models/Downloads/AsynchronousOperation.swift",
    "content": "//\n//  AsynchronousOperation.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 03/10/2018.\n//  Copyright © 2018 John Coates. All rights reserved.\n//  From https://stackoverflow.com/questions/32322386/how-to-download-multiple-files-sequentially-using-nsurlsession-downloadtask-in-s\n\nimport Foundation\n/// Asynchronous operation base class\n///\n/// This is abstract to class performs all of the necessary KVN of `isFinished` and\n/// `isExecuting` for a concurrent `Operation` subclass. You can subclass this and\n/// implement asynchronous operations. All you must do is:\n///\n/// - override `main()` with the tasks that initiate the asynchronous task;\n///\n/// - call `completeOperation()` function when the asynchronous task is done;\n///\n/// - optionally, periodically check `self.cancelled` status, performing any clean-up\n///   necessary and then ensuring that `finish()` is called; or\n///   override `cancel` method, calling `super.cancel()` and then cleaning-up\n///   and ensuring `finish()` is called.\n\nclass AsynchronousOperation: Operation {\n\n    /// State for this operation.\n\n    @objc private enum OperationState: Int {\n        case ready\n        case executing\n        case finished\n    }\n\n    /// Concurrent queue for synchronizing access to `state`.\n\n    private let stateQueue = DispatchQueue(label: Bundle.main.bundleIdentifier! + \".rw.state\", attributes: .concurrent)\n\n    /// Private backing stored property for `state`.\n\n    private var rawState: OperationState = .ready\n\n    /// The state of the operation\n\n    @objc private dynamic var state: OperationState {\n        get { return stateQueue.sync { rawState } }\n        set { stateQueue.sync(flags: .barrier) { rawState = newValue } }\n    }\n\n    // MARK: - Various `Operation` properties\n\n    open         override var isReady: Bool { return state == .ready && super.isReady }\n    public final override var isExecuting: Bool { return state == .executing }\n    public final override var isFinished: Bool { return state == .finished }\n\n    // KVN for dependent properties\n\n    open override class func keyPathsForValuesAffectingValue(forKey key: String) -> Set<String> {\n        if [\"isReady\", \"isFinished\", \"isExecuting\"].contains(key) {\n            return [#keyPath(state)]\n        }\n\n        return super.keyPathsForValuesAffectingValue(forKey: key)\n    }\n\n    // Start\n\n    public final override func start() {\n        if isCancelled {\n            finish()\n            return\n        }\n\n        state = .executing\n\n        main()\n    }\n\n    /// Subclasses must implement this to perform their work and they must not call `super`.\n    /// The default implementation of this function throws an exception.\n\n    open override func main() {\n        fatalError(\"Subclasses must implement `main`.\")\n    }\n\n    /// Call this function to finish an operation that is currently executing\n\n    public final func finish() {\n        if isExecuting { state = .finished }\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Models/Downloads/DownloadManager.swift",
    "content": "//\n//  DownloadManager.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 03/10/2018.\n//  Copyright © 2018 John Coates. All rights reserved.\n\nimport Cocoa\n\n/// Manager of asynchronous download `Operation` objects\n\nfinal class DownloadManager: NSObject {\n\n    /// Dictionary of operations, keyed by the `taskIdentifier` of the `URLSessionTask`\n\n    fileprivate var operations = [Int: DownloadOperation]()\n\n    /// Serial OperationQueue for downloads\n\n    private let queue: OperationQueue = {\n        let operationQueue = OperationQueue()\n        operationQueue.name = \"download\"\n        operationQueue.maxConcurrentOperationCount = 3\n        return operationQueue\n    }()\n\n    /// Delegate-based `URLSession` for DownloadManager\n\n    lazy var session: URLSession = {\n        let configuration = URLSessionConfiguration.default\n        return URLSession(configuration: configuration, delegate: self, delegateQueue: nil)\n    }()\n\n    /// Add download\n    ///\n    /// - parameter URL:  The URL of the file to be downloaded\n    ///          folder:  The name of the subfolder where the file will be stored\n    ///\n    /// - returns:        The DownloadOperation of the operation that was queued\n\n    @discardableResult\n    func queueDownload(_ url: URL, folder: String) -> DownloadOperation {\n        let operation = DownloadOperation(session: session, url: url, folder: folder)\n        operations[operation.task.taskIdentifier] = operation\n        queue.addOperation(operation)\n        return operation\n    }\n\n    /// Cancel all queued operations\n\n    func cancelAll() {\n        queue.cancelAllOperations()\n    }\n\n}\n\n// MARK: URLSessionDownloadDelegate methods\n\nextension DownloadManager: URLSessionDownloadDelegate {\n\n    func urlSession(\n        _ session: URLSession,\n        downloadTask: URLSessionDownloadTask,\n        didFinishDownloadingTo location: URL\n    ) {\n        operations[downloadTask.taskIdentifier]?.urlSession(session,\n                                                            downloadTask: downloadTask,\n                                                            didFinishDownloadingTo: location)\n    }\n\n    func urlSession(\n        _ session: URLSession,\n        downloadTask: URLSessionDownloadTask,\n        didWriteData bytesWritten: Int64,\n        totalBytesWritten: Int64,\n        totalBytesExpectedToWrite: Int64\n    ) {\n        operations[downloadTask.taskIdentifier]?.urlSession(session,\n                                                            downloadTask: downloadTask,\n                                                            didWriteData: bytesWritten,\n                                                            totalBytesWritten: totalBytesWritten,\n                                                            totalBytesExpectedToWrite: totalBytesExpectedToWrite)\n    }\n}\n\n// MARK: URLSessionTaskDelegate methods\n\nextension DownloadManager: URLSessionTaskDelegate {\n\n    func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {\n        let key = task.taskIdentifier\n        operations[key]?.urlSession(session, task: task, didCompleteWithError: error)\n        operations.removeValue(forKey: key)\n    }\n\n}\n\n/// Asynchronous Operation subclass for downloading\n\nfinal class DownloadOperation: AsynchronousOperation {\n    let task: URLSessionTask\n    let folder: String\n\n    init(session: URLSession, url: URL, folder: String) {\n        self.folder = folder\n        task = session.downloadTask(with: url)\n        super.init()\n    }\n\n    override func cancel() {\n        task.cancel()\n        super.cancel()\n    }\n\n    override func main() {\n        task.resume()\n    }\n}\n\n// MARK: NSURLSessionDownloadDelegate methods\n//       Customized for our usage\nextension DownloadOperation: URLSessionDownloadDelegate {\n    // This is where we save the file to its location\n    func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {\n        do {\n            // We may need to create our destination\n            let destinationDirectory = Cache.supportPath.appending(\"/\" + folder)\n            FileHelpers.createDirectory(atPath: destinationDirectory)\n\n            let manager = FileManager.default\n            let supportURL = URL(fileURLWithPath: Cache.supportPath.appending(\"/\" + folder))\n\n            debugLog(\"Caching \\(downloadTask.originalRequest!.url!.lastPathComponent) at \\(folder)\")\n\n            // The file may exist, remove it\n            try? manager.removeItem(at: supportURL.appendingPathComponent(\n                                        downloadTask.originalRequest!.url!.lastPathComponent))\n\n            // Finally move the file\n            try manager.moveItem(at: location, to: supportURL.appendingPathComponent(\n                                    downloadTask.originalRequest!.url!.lastPathComponent))\n        } catch {\n            errorLog(\"\\(error)\")\n        }\n    }\n\n    func urlSession(\n        _ session: URLSession,\n        downloadTask: URLSessionDownloadTask,\n        didWriteData bytesWritten: Int64,\n        totalBytesWritten: Int64,\n        totalBytesExpectedToWrite: Int64\n    ) {\n        // let progress = Double(totalBytesWritten) / Double(totalBytesExpectedToWrite)\n        // print(\"\\(downloadTask.originalRequest!.url!.absoluteString) \\(progress)\")\n    }\n}\n\n// MARK: URLSessionTaskDelegate methods\n\nextension DownloadOperation: URLSessionTaskDelegate {\n\n    func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {\n        defer { finish() }\n\n        if let error = error {\n            errorLog(\"\\(error)\")\n            return\n        }\n\n        let destinationDirectory = Cache.supportPath.appending(\"/\" + folder)\n\n        // Some manifests come in tar form, in that case untar them here\n        if folder == \"tvOS 13\" {\n            FileHelpers.unTar(file: destinationDirectory.appending(\"/resources-13.tar\"), atPath: destinationDirectory)\n        } else if folder == \"tvOS 16\" {\n            FileHelpers.unTar(file: destinationDirectory.appending(\"/resources-16.tar\"), atPath: destinationDirectory)\n        } else if folder == \"tvOS 12\" {\n            FileHelpers.unTar(file: destinationDirectory.appending(\"/resources.tar\"), atPath: destinationDirectory)\n        } else if folder == \"macOS 14\" {\n            FileHelpers.unTar(file: destinationDirectory.appending(\"/resources-14-0-10.tar\"), atPath: destinationDirectory)\n        } else if folder == \"macOS 15\" {\n            FileHelpers.unTar(file: destinationDirectory.appending(\"/resources-15-0-2.tar\"), atPath: destinationDirectory)\n        } else if folder == \"macOS 26\" {\n            FileHelpers.unTar(file: destinationDirectory.appending(\"/resources-26-0-1.tar\"), atPath: destinationDirectory)\n        }\n\n        debugLog(\"Finished downloading \\(task.originalRequest!.url!.absoluteString)\")\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Models/Downloads/FileHelpers.swift",
    "content": "//\n//  FileHelpers.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 08/07/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Foundation\n\nstruct FileHelpers {\n    static func createDirectory(atPath: String) {\n        let fileManager = FileManager.default\n        if fileManager.fileExists(atPath: atPath) == false {\n            do {\n                try fileManager.createDirectory(atPath: atPath,\n                                                withIntermediateDirectories: true, attributes: nil)\n            } catch let error {\n                errorLog(\"Couldn't create directory at \\(atPath) : \\(error)\")\n                errorLog(\"FATAL : There's nothing more we can do at this point, please report\")\n            }\n        }\n    }\n\n    static func unTar(file: String, atPath: String) {\n        let process: Process = Process()\n\n        debugLog(\"untaring \\(file) at \\(atPath)\")\n        process.currentDirectoryPath = atPath\n        process.launchPath = \"/usr/bin/tar\"\n        process.arguments = [\"-xvf\", file]\n\n        process.launch()\n\n        process.waitUntilExit()\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Models/ErrorLog.swift",
    "content": "//\n//  ErrorLog.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 17/10/2018.\n//  Copyright © 2018 John Coates. All rights reserved.\n//\n\nimport Cocoa\nimport os.log\n\nenum ErrorLevel: Int {\n    case info, debug, warning, error\n}\n\nfinal class LogMessage {\n    let date: Date\n    let level: ErrorLevel\n    let message: String\n    var actionName: String?\n    var actionBlock: BlockOperation?\n\n    init(level: ErrorLevel, message: String) {\n        self.level = level\n        self.message = message\n        self.date = Date()\n    }\n}\n\ntypealias LoggerCallback = (ErrorLevel) -> Void\n\nfinal class Logger {\n    static let sharedInstance = Logger()\n\n    var callbacks = [LoggerCallback]()\n\n    func addCallback(_ callback:@escaping LoggerCallback) {\n        callbacks.append(callback)\n    }\n\n    func callBack(level: ErrorLevel) {\n        DispatchQueue.main.async {\n            for callback in self.callbacks {\n                callback(level)\n            }\n        }\n    }\n}\nvar errorMessages = [LogMessage]()\n/*\nfunc appSupportPath() -> String {\n    var appPath = \"\"\n\n    // Grab an array of Application Support paths\n    let appSupportPaths = NSSearchPathForDirectoriesInDomains(\n        .applicationSupportDirectory,\n        .userDomainMask,\n        true)\n\n    if appSupportPaths.isEmpty {\n        errorLog(\"FATAL : app support does not exist!\")\n        return \"/\"\n    }\n\n    appPath = appSupportPaths[0]\n\n    let appSupportDirectory = appPath as NSString\n\n    return appSupportDirectory.appendingPathComponent(\"Aerial\")\n}*/\n\n// This will clear the existing log if > 1MB\n// This is called at startup\nfunc rollLogIfNeeded() {\n    let cacheDirectory = Cache.supportPath\n    // if let cacheDirectory = path() {\n    var cacheFileUrl = URL(fileURLWithPath: cacheDirectory as String)\n    \n    if Aerial.helper.underCompanion {\n        cacheFileUrl.appendPathComponent(\"AerialUnderCompanionLog.txt\")\n    } else {\n        cacheFileUrl.appendPathComponent(\"AerialLog.txt\")\n    }\n    \n    if FileManager.default.fileExists(atPath: cacheFileUrl.path) {\n        do {\n            let resourceValues = try cacheFileUrl.resourceValues(forKeys: [.fileSizeKey])\n            let fileSize = Int64(resourceValues.fileSize!)\n\n            if (fileSize > 1000000) {\n                try FileManager.default.removeItem(at: cacheFileUrl)\n            }\n                \n        } catch {\n            logToConsole(error.localizedDescription)\n        }\n    }\n}\n\n// swiftlint:disable:next identifier_name\nfunc Log(level: ErrorLevel, message: String) {\n    #if DEBUG\n    print(\"\\(message)\\n\")\n    #endif\n\n    errorMessages.append(LogMessage(level: level, message: message))\n\n    // We report errors to Console.app\n    if level == .error {\n        if #available(OSX 10.12, *) {\n            // This is faster when available\n            let log = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: \"Screensaver\")\n            os_log(\"AerialError: %{public}@\", log: log, type: .error, message)\n        } else {\n            NSLog(\"AerialError: \\(message)\")\n        }\n    }\n\n    // We may have set callbacks\n    if level == .warning || level == .error || (level == .debug && PrefsAdvanced.debugMode) {\n        Logger.sharedInstance.callBack(level: level)\n    }\n\n    // Log to disk\n    if PrefsAdvanced.debugMode {\n        logToConsole(message)\n        logToDisk(message)\n    }\n}\n\nfunc logToConsole(_ message: String) {\n    if #available(OSX 10.12, *) {\n        // This is faster when available\n        let log = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: \"Screensaver\")\n        os_log(\"Aerial: %{public}@\", log: log, type: .default, message)\n    } else {\n        NSLog(\"Aerial: \\(message)\")\n    }\n\n}\nfunc logToDisk(_ message: String) {\n    DispatchQueue.main.async {\n        // Prefix message with date\n        let dateFormatter = DateFormatter()\n        dateFormatter.dateFormat = \"yyyy-MM-dd HH:mm:ss.SSS\"\n        let string = dateFormatter.string(from: Date()) + \" : \" + message + \"\\n\"\n\n        // if let cacheDirectory = VideoCache.appSupportDirectory {\n\n        let cacheDirectory = Cache.supportPath        // if let cacheDirectory = path() {\n        var cacheFileUrl = URL(fileURLWithPath: cacheDirectory as String)\n        \n        if Aerial.helper.underCompanion {\n            cacheFileUrl.appendPathComponent(\"AerialUnderCompanionLog.txt\")\n        } else {\n            cacheFileUrl.appendPathComponent(\"AerialLog.txt\")\n        }\n\n        let data = string.data(using: String.Encoding.utf8, allowLossyConversion: false)!\n\n        if FileManager.default.fileExists(atPath: cacheFileUrl.path) {\n            // Append to log\n            do {\n                let fileHandle = try FileHandle(forWritingTo: cacheFileUrl)\n                fileHandle.seekToEndOfFile()\n                fileHandle.write(data)\n                fileHandle.closeFile()\n            } catch {\n                NSLog(\"AerialError: Can't open handle for AerialLog.txt\")\n            }\n        } else {\n            // Create new log\n            do {\n                try data.write(to: cacheFileUrl, options: .atomic)\n            } catch {\n                NSLog(\"AerialError: Can't write to file AerialLog.txt\")\n            }\n        }\n        // }\n    }\n}\n\nfunc debugLog(_ message: String) {\n    // Comment the condition to always log debug mode\n    if PrefsAdvanced.debugMode {\n        Log(level: .debug, message: message)\n    }\n}\n\nfunc infoLog(_ message: String) {\n    Log(level: .info, message: message)\n}\n\nfunc warnLog(_ message: String) {\n    Log(level: .warning, message: message)\n}\n\nfunc errorLog(_ message: String) {\n    Log(level: .error, message: \"🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨 \" + message)\n}\n"
  },
  {
    "path": "Aerial/Source/Models/Extensions/AVAsset+VideoOrientation.swift",
    "content": "//\n//  AVAsset+VideoOrientation.swift\n//  AVAsset+VideoOrientation\n//\n//  Created by Guillaume Louel on 26/08/2021.\n//  Copyright © 2021 Guillaume Louel. All rights reserved.\n//\n//  Created by Wesley Van der Klomp on 1/7/19.\n//\n// Translated from: https://gist.github.com/lukabernardi/5020724\n//\n// Modified to add some extra checks\n\nimport AVFoundation\n\nextension AVAsset {\n\n    enum VideoOrientation {\n        case right, up, left, down\n\n        static func fromVideoWithAngle(ofDegree degree: CGFloat) -> VideoOrientation? {\n            switch Int(degree) {\n            case 0: return .right\n            case 90: return .up\n            case 180: return .left\n            case -90: return .down\n            default: return nil\n            }\n        }\n    }\n\n    // This also checks for videos that may have their rotation baked in,\n    // and not provided as a metadata (so 1080x1920 instead of 1920x1080 with 90° rotation)\n    func isVertical() -> Bool {\n        if self.videoOrientation() == .right || self.videoOrientation() == .left {\n            // So at this point this is the natural(ish) orientation, we need to check the width/height\n            let track = self.tracks(withMediaType: .video).first!\n\n            return track.naturalSize.height > track.naturalSize.width\n        } else {\n            return true\n        }\n    }\n\n    // This checks for a rotation metadata ONLY which is what works for iPhone videos.\n    func videoOrientation() -> VideoOrientation? {\n        func radiansToDegrees(_ radians: Float) -> CGFloat {\n            return CGFloat(radians * 180.0 / Float.pi)\n        }\n\n        guard let firstVideoTrack = self.tracks(withMediaType: .video).first else {\n            return nil\n        }\n        let transform = firstVideoTrack.preferredTransform\n        let videoAngleInDegree = radiansToDegrees(atan2f(Float(transform.b), Float(transform.a)))\n        return VideoOrientation.fromVideoWithAngle(ofDegree: videoAngleInDegree)\n    }\n\n}\nimport Foundation\n"
  },
  {
    "path": "Aerial/Source/Models/Extensions/AVPlayerItem+vibrance.swift",
    "content": "//\n//  AVPlayerItem+vibrance.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 02/08/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport AVKit\n\nextension AVPlayerItem {\n    func setVibrance(_ value: Double) {\n        var useValue = PrefsVideos.globalVibrance\n        \n        if value != 0 {\n            useValue = value\n        }\n        \n        guard useValue != 0 else {\n            return\n        }\n        \n        if #available(OSX 10.14, *) {\n            debugLog(\"Applying vibrance of \\(useValue)\")\n            let filter = CIFilter(name: \"CIVibrance\")!\n            self.videoComposition = AVVideoComposition(asset: asset, applyingCIFiltersWithHandler: { request in\n                let source = request.sourceImage.clampedToExtent()\n                filter.setValue(source, forKey: kCIInputImageKey)\n                filter.setValue(useValue, forKey: kCIInputAmountKey)\n                let output = filter.outputImage\n                \n                request.finish(with: output!, context: nil)\n            })\n        }\n    }\n    \n    func setColorInvert() {\n        if #available(OSX 10.14, *) {\n            debugLog(\"Applying color invert\")\n\n            if let invertFilter = CIFilter(name: \"CIColorInvert\") {\n                let context = CIContext(options: [.workingColorSpace: CGColorSpace(name: CGColorSpace.sRGB)!])\n                \n                self.videoComposition = AVVideoComposition(asset: asset, applyingCIFiltersWithHandler: { request in\n                    let source = request.sourceImage.clampedToExtent()\n                    \n                    invertFilter.setValue(source, forKey: kCIInputImageKey)\n                    \n                    guard let output = invertFilter.outputImage else {\n                        request.finish(with: source, context: nil)\n                        return\n                    }\n                    \n                    request.finish(with: output, context: context)\n                })\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Models/Extensions/AVPlayerViewExtension.swift",
    "content": "//\n//  AVPlayerViewExtension.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 16/10/2018.\n//  Copyright © 2018 John Coates. All rights reserved.\n//\n\nimport Foundation\nimport Cocoa\nimport AVKit\n\nextension AVPlayerView {\n\n    override open func scrollWheel(with event: NSEvent) {\n        // Disable scrolling that can cause accidental video playback control (seek)\n        return\n    }\n\n    override open func keyDown(with event: NSEvent) {\n        // Disable space key (do not pause video playback)\n\n        let spaceBarKeyCode = UInt16(49)\n        if event.keyCode == spaceBarKeyCode {\n            return\n        }\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Models/Extensions/DispatchQueue+Extension.swift",
    "content": "//\n//  DispatchQueue+Extension.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 28/12/2021.\n//  Copyright © 2021 Guillaume Louel. All rights reserved.\n//\n\nimport Foundation\n\nextension DispatchQueue {\n\n    static func background(delay: Double = 0.0, background: (() -> Void)? = nil, completion: (() -> Void)? = nil) {\n        DispatchQueue.global(qos: .background).async {\n            background?()\n            if let completion = completion {\n                DispatchQueue.main.asyncAfter(deadline: .now() + delay, execute: {\n                    completion()\n                })\n            }\n        }\n    }\n\n}\n"
  },
  {
    "path": "Aerial/Source/Models/Extensions/NSButton+icons.swift",
    "content": "//\n//  NSButton+icons.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 01/08/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Foundation\n\nimport Cocoa\n\nextension NSButton {\n    func setIcons(_ named: String) {\n        self.image = Aerial.helper.getMiniSymbol(named)\n        self.image?.isTemplate = true\n    }\n\n    func setLargeIcon(_ named: String) {\n        self.image = Aerial.helper.getSymbol(named)!.tinting(with: .secondaryLabelColor)\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Models/Extensions/NSImage+trim.swift",
    "content": "//\n//  NSImage+trim.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 23/04/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Cocoa\n\nextension NSImage {\n    func trim() -> NSImage? {\n        var imageRect = CGRect(x: 0, y: 0, width: self.size.width, height: self.size.height)\n        let imageRef = self.cgImage(forProposedRect: &imageRect, context: nil, hints: nil)\n\n        let trimTo = self.getTrimmedRect()\n        // let cutRef = imageRef?.cropping(to: trimTo)\n\n        guard let cutRef = imageRef?.cropping(to: trimTo) else {\n            return nil\n        }\n\n        return NSImage(cgImage: cutRef, size: trimTo.size)\n    }\n\n    // There might be a better way to do this but that's all I found...\n    // swiftlint:disable:next cyclomatic_complexity\n    private func getTrimmedRect() -> CGRect {\n        let bmp = self.representations[0] as! NSBitmapImageRep\n        let data: UnsafeMutablePointer<UInt8> = bmp.bitmapData!\n        var alpha: UInt8\n\n        var topCrop = 0\n        var bottomCrop = bmp.pixelsHigh\n        var leftCrop = 0\n        var rightCrop = bmp.pixelsWide\n\n        // Top crop\n        outerTop: for row in 0..<bmp.pixelsHigh {\n            for col in 0..<bmp.pixelsWide {\n                alpha = data[(bmp.pixelsWide * row + col) * 4 + 3]\n\n                if alpha != 0 {\n                    topCrop = row\n                    break outerTop\n                }\n            }\n        }\n\n        // Bottom crop\n        outerBottom: for row in (0..<bmp.pixelsHigh).reversed() {\n            for col in 0..<bmp.pixelsWide {\n                alpha = data[(bmp.pixelsWide * row + col) * 4 + 3]\n\n                if alpha != 0 {\n                    bottomCrop = row\n                    break outerBottom\n                }\n            }\n        }\n\n        // Left crop\n        outerLeft: for col in 0..<bmp.pixelsWide {\n            for row in 0..<bmp.pixelsHigh {\n                alpha = data[(bmp.pixelsWide * row + col) * 4 + 3]\n\n                if alpha != 0 {\n                    leftCrop = col\n                    break outerLeft\n                }\n            }\n        }\n\n        // Right crop\n        outerRight: for col in (0..<bmp.pixelsWide).reversed() {\n            for row in 0..<bmp.pixelsHigh {\n                alpha = data[(bmp.pixelsWide * row + col) * 4 + 3]\n\n                if alpha != 0 {\n                    rightCrop = col\n                    break outerRight\n                }\n            }\n        }\n\n        return CGRect(x: leftCrop, y: topCrop, width: rightCrop-leftCrop, height: bottomCrop-topCrop)\n    }\n\n    func tinting(with tintColor: NSColor) -> NSImage {\n        guard let cgImage = self.cgImage(forProposedRect: nil, context: nil, hints: nil) else { return self }\n\n        return NSImage(size: size, flipped: false) { bounds in\n            guard let context = NSGraphicsContext.current?.cgContext else { return false }\n\n            tintColor.set()\n            context.clip(to: bounds, mask: cgImage)\n            context.fill(bounds)\n\n            return true\n        }\n    }\n\n}\n"
  },
  {
    "path": "Aerial/Source/Models/Extensions/NSMenuItem+icons.swift",
    "content": "//\n//  NSMenuItem+icons.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 30/07/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Cocoa\n\nextension NSMenuItem {\n    func setIcons(_ named: String) {\n        self.image = Aerial.helper.getMiniSymbol(named)\n        self.image?.isTemplate = true\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Models/Hardware/Battery.swift",
    "content": "//\n//  Battery.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 06/12/2019.\n//  Copyright © 2019 John Coates. All rights reserved.\n//\n\nimport Foundation\n\nstruct Battery {\n\n    // MARK: - Battery detection\n    static func isUnplugged() -> Bool {\n        return IOPSGetTimeRemainingEstimate() != kIOPSTimeRemainingUnlimited\n    }\n\n    static func isCharging() -> Bool {\n        let timeRemaining: CFTimeInterval = IOPSGetTimeRemainingEstimate()\n        if timeRemaining == -2.0 {\n            return true\n        } else {\n            return false\n        }\n    }\n\n    static func isLow() -> Bool {\n        let batteryLevel = getRemainingPercent()\n\n        // If we have no battery, we'll get 0, so in that case we're NOT low\n        if batteryLevel == 0 {\n            return false\n        }\n\n        return batteryLevel < 20\n    }\n\n    static func getRemainingPercent() -> Int {\n        // Take a snapshot of all the power source info\n        guard let snapshot = IOPSCopyPowerSourcesInfo()?.takeRetainedValue()\n            else { return 0 }\n\n        // Pull out a list of power sources\n        guard let sources: NSArray = IOPSCopyPowerSourcesList(snapshot)?.takeRetainedValue()\n            else { return 0 }\n\n        // swiftlint:disable:next empty_count\n        if sources.count > 0 {\n            // For each power source...\n            for ps in sources {\n                // Fetch the information for a given power source out of our snapshot\n                guard let info: NSDictionary = IOPSGetPowerSourceDescription(snapshot, ps as CFTypeRef)?.takeUnretainedValue()\n                    else { return 0 }\n\n                // Pull out the name and current capacity\n                if let capacity = info[kIOPSCurrentCapacityKey] as? Int,\n                    let max = info[kIOPSMaxCapacityKey] as? Int {\n\n                    return Int(Double(capacity)/Double(max)*100)\n                }\n            }\n        }\n\n        return 0\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Models/Hardware/Brightness.swift",
    "content": "//\n//  Brightness.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 18/12/2019.\n//  Copyright © 2019 Guillaume Louel. All rights reserved.\n//\n\nimport Foundation\n\nstruct Brightness {\n\n    static func get() -> Float {\n        let service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching(\"IODisplayConnect\"))\n        let pointer = UnsafeMutablePointer<Float>.allocate(capacity: 1)\n        IODisplayGetFloatParameter(service, 0, kIODisplayBrightnessKey as CFString, pointer)\n        let brightness = pointer.pointee\n        IOObjectRelease(service)\n        return brightness\n    }\n\n    static func set(level: Float) {\n        let service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching(\"IODisplayConnect\"))\n        IODisplaySetFloatParameter(service, 0, kIODisplayBrightnessKey as CFString, level)\n        IOObjectRelease(service)\n    }\n\n}\n"
  },
  {
    "path": "Aerial/Source/Models/Hardware/DarkMode.swift",
    "content": "//\n//  DarkMode.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 19/12/2019.\n//  Copyright © 2019 Guillaume Louel. All rights reserved.\n//\n\nimport Foundation\nimport Cocoa\n\nstruct DarkMode {\n    static func isAvailable() -> (Bool, reason: String) {\n        if #available(OSX 10.14, *) {\n            if Aerial.helper.darkMode {\n                return (true, \"Your Mac is currently in Dark Mode\")\n            } else {\n                return (true, \"Your Mac is currently in Light Mode\")\n            }\n        } else {\n            // Fallback on earlier versions\n            return (false, \"macOS 10.14 Mojave or above is required\")\n        }\n    }\n\n    static func isEnabled() -> Bool {\n        return Aerial.helper.darkMode\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Models/Hardware/DisplayDetection.swift",
    "content": "//\n//  DisplayDetection.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 09/05/2019.\n//  Copyright © 2019 John Coates. All rights reserved.\n//\n\nimport Foundation\nimport Cocoa\n\nclass Screen: NSObject {\n    var id: CGDirectDisplayID\n    var width: Int\n    var height: Int\n    var bottomLeftFrame: CGRect\n    var topRightCorner: CGPoint\n    var zeroedOrigin: CGPoint\n    var isMain: Bool\n    var backingScaleFactor: CGFloat\n\n    init(id: CGDirectDisplayID, width: Int, height: Int, bottomLeftFrame: CGRect, isMain: Bool, backingScaleFactor: CGFloat) {\n        self.id = id\n        self.width = width\n        self.height = height\n        self.bottomLeftFrame = bottomLeftFrame\n        // We precalculate the right corner too, as we will need this !\n        self.topRightCorner = CGPoint(x: bottomLeftFrame.origin.x + CGFloat(width),\n                                      y: bottomLeftFrame.origin.y + CGFloat(height))\n        self.zeroedOrigin = CGPoint(x: 0, y: 0)\n        self.isMain = isMain\n        self.backingScaleFactor = backingScaleFactor\n    }\n\n    override var description: String {\n        return \"[id=\\(self.id), width=\\(self.width), height=\\(self.height), bottomLeftFrame=\\(self.bottomLeftFrame), topRightCorner=\\(self.topRightCorner), isMain=\\(self.isMain), backingScaleFactor=\\(self.backingScaleFactor)]\"\n    }\n}\n\n// swiftlint:disable:next type_body_length\nfinal class DisplayDetection: NSObject {\n    static let sharedInstance = DisplayDetection()\n\n    var screens = [Screen]()\n    var unusedScreens = [Screen]()\n\n    var cmInPoints: CGFloat = 40\n    var maxLeftScreens: CGFloat = 0\n    var maxBelowScreens: CGFloat = 0\n\n    var advancedScreenRect: CGRect?\n    var advancedZeroedScreenRect: CGRect?\n\n    // MARK: - Lifecycle\n    override init() {\n        super.init()\n        debugLog(\"📺 Display Detection initialized\")\n        detectDisplays()\n    }\n\n    func resetUnusedScreens() {\n        debugLog(\"📺 reset unused screens\")\n        unusedScreens = screens\n        debugLog(\"📺☢️ s \\(screens.count) us \\(unusedScreens.count)\")\n    }\n    \n    // MARK: - Detection\n    func detectDisplays() {\n        // Display detection is done in two passes :\n        // - Through CGDisplay, we grab all online screens (connected, but\n        //   may or may not be powered on !) and get most information needed\n        // - Through NSScreen to get the backingScaleFactor (retinaness of a screen)\n\n        // Cleanup a bit in case of redetection\n        screens = [Screen]()\n        maxLeftScreens = 0\n        maxBelowScreens = 0\n\n        // First pass\n        let maxDisplays: UInt32 = 32\n        var onlineDisplays = [CGDirectDisplayID](repeating: 0, count: Int(maxDisplays))\n        var displayCount: UInt32 = 0\n\n        _ = CGGetOnlineDisplayList(maxDisplays, &onlineDisplays, &displayCount)\n        debugLog(\"\\(displayCount) display(s) detected\")\n        var mainID: CGDirectDisplayID?\n\n        for currentDisplay in onlineDisplays[0..<Int(displayCount)] {\n            let isMain = CGDisplayIsMain(currentDisplay)\n\n            if isMain == 1 {\n                // We calculate the equivalent of a centimeter in points on the main screen as a reference\n                let mmsize = CGDisplayScreenSize(currentDisplay)\n                let wide = CGDisplayPixelsWide(currentDisplay)\n                cmInPoints = CGFloat(wide) / CGFloat(mmsize.width) * 10\n                debugLog(\"1cm = \\(cmInPoints) points\")\n                mainID = currentDisplay\n            }\n        }\n\n        // Second pass on NSScreen to grab the retina factor\n        for screen in NSScreen.screens {\n            let screenID = screen.deviceDescription[NSDeviceDescriptionKey(\"NSScreenNumber\")] as! CGDirectDisplayID\n\n            var thisIsMain = false\n            if screenID == mainID {\n                thisIsMain = true\n            }\n\n            screens.append(Screen(id: screenID,\n                                  width: Int(screen.frame.width),\n                                  height: Int(screen.frame.height),\n                                  bottomLeftFrame: screen.frame,\n                                  isMain: thisIsMain,\n                                  backingScaleFactor: screen.backingScaleFactor))\n        }\n\n        // Before we finish, we calculate the origin of each screen from a 0,0 perspective\n        // This calculation is pretty different in advanced mode so it got split up\n        if PrefsDisplays.displayMarginsAdvanced && !advancedMargins.displays.isEmpty {\n            calculateAdvancedZeroedOrigins()\n        } else {\n            calculateZeroedOrigins()\n        }\n\n        for screen in screens {\n            debugLog(\"📺 found \\(screen)\")\n        }\n\n        // We store the list to pluck it later\n        unusedScreens = screens\n        \n        debugLog(\"\\(getGlobalScreenRect())\")\n    }\n\n    func getScreenCount() -> Int {\n        var count = 0\n        for screen in screens where screen.height > 200 {\n            count += 1\n        }\n\n        return count\n    }\n\n    // MARK: - Helpers\n    // Regular calculation\n    func calculateZeroedOrigins() {\n        let orect = getGlobalScreenRect()\n\n        for screen in screens {\n            debugLog(\"src orig : \\(screen.bottomLeftFrame.origin)\")\n\n            let (leftScreens, belowScreens) = detectBorders(forScreen: screen)\n\n            if leftScreens > maxLeftScreens {\n                maxLeftScreens = leftScreens\n            }\n            if belowScreens > maxBelowScreens {\n                maxBelowScreens = belowScreens\n            }\n\n            screen.zeroedOrigin = CGPoint(x: screen.bottomLeftFrame.origin.x - orect.origin.x + (leftScreens * leftMargin()),\n                                          y: screen.bottomLeftFrame.origin.y - orect.origin.y + (belowScreens * belowMargin()))\n        }\n    }\n\n    // Advanced calculation, this is a bit messy...\n    func calculateAdvancedZeroedOrigins() {\n        // 2 pass, first we calculate the real position of each screen with offsets applied\n        for screen in screens {\n            debugLog(\"Asrc orig : \\(screen.bottomLeftFrame.origin)\")\n            var offsetleft: CGFloat = 0\n            var offsettop: CGFloat = 0\n\n            if let display = findDisplayAdvancedMargins(posx: screen.bottomLeftFrame.origin.x, posy: screen.bottomLeftFrame.origin.y) {\n                offsetleft = display.offsetleft\n                offsettop = display.offsettop\n            }\n\n            // These are NOT zeroed at this point !!!\n            screen.zeroedOrigin = CGPoint(x: screen.bottomLeftFrame.origin.x + (offsetleft * cmInPoints),\n                                          y: screen.bottomLeftFrame.origin.y + (offsettop * cmInPoints))\n        }\n\n        // We get an intermediate representation of whole bunch, non zeroed\n        let irect = getIntermediateAdvancedScreenRect()\n        advancedScreenRect = irect  // We store this for later...\n        // And now we zero them !\n        for screen in screens {\n            screen.zeroedOrigin = CGPoint(x: screen.zeroedOrigin.x - irect.origin.x,\n                                          y: screen.zeroedOrigin.y - irect.origin.y)\n            debugLog(\"Zorig : \\(screen.zeroedOrigin)\")\n        }\n\n        // Now that zeroed is really zeroed, we can cheat a bit\n        let i0rect = getIntermediateAdvancedScreenRect()\n        advancedZeroedScreenRect = i0rect  // We store this for later...\n\n        let orect = getGlobalScreenRect()\n        debugLog(\"Orect : \\(orect)\")\n    }\n\n    // Border detection\n    // This will work for most cases, but will fail in some grid/tetris like arrangements\n    func detectBorders(forScreen: Screen) -> (CGFloat, CGFloat) {\n        var leftScreens: CGFloat = 0\n        var belowScreens: CGFloat = 0\n\n        for screen in screens where screen != forScreen {\n            if screen.bottomLeftFrame.origin.x < forScreen.bottomLeftFrame.origin.x &&\n                screen.bottomLeftFrame.origin.x + CGFloat(screen.width) <=\n                forScreen.bottomLeftFrame.origin.x {\n                leftScreens += 1\n            }\n            if screen.bottomLeftFrame.origin.y < forScreen.bottomLeftFrame.origin.y &&\n                screen.bottomLeftFrame.origin.y + CGFloat(screen.height) <=\n                forScreen.bottomLeftFrame.origin.y {\n                belowScreens += 1\n            }\n        }\n        debugLog(\"left \\(leftScreens) below \\(belowScreens)\")\n\n        return (leftScreens, belowScreens)\n    }\n\n    func leftMargin() -> CGFloat {\n        return cmInPoints * CGFloat(PrefsDisplays.horizontalMargin)\n    }\n\n    func belowMargin() -> CGFloat {\n        return cmInPoints * CGFloat(PrefsDisplays.verticalMargin)\n    }\n\n    func findScreenWith(frame: CGRect) -> Screen? {\n        for screen in screens where frame == screen.bottomLeftFrame {\n            return screen\n        }\n\n        return nil\n    }\n    \n    func alternateFindScreenWith(frame: CGRect) -> Screen? {\n        debugLog(\"📺☢️ fs : \\(frame.size.debugDescription)\")\n        // This is a really simple workaround, we look at the size only, and with the screen list in reverse which seems to kindaaaa match ?\n        // We temporarily ignore bsf as we may not be able to access view.window this early it seems\n\n        debugLog(\"📺☢️ s \\(screens.count) us \\(unusedScreens.count)\")\n        \n        for i in (0 ..< unusedScreens.count).reversed() {\n            if unusedScreens[i].bottomLeftFrame.size == frame.size {\n                let foundScreen = unusedScreens[i]\n                unusedScreens.remove(at: i)\n                debugLog(\"foundScreen : \\(foundScreen.bottomLeftFrame.debugDescription)\")\n                return foundScreen\n            }\n        }\n        \n        return nil\n    }\n\n\n    func findScreenWith(id: CGDirectDisplayID) -> Screen? {\n        for screen in screens where screen.id == id {\n            return screen\n        }\n\n        return nil\n    }\n    \n    func markScreenAsUsed(id: CGDirectDisplayID) {\n        // remove the screen from the unused list\n        debugLog(\"pre filter \\(unusedScreens.count)\")\n        let filteredScreens = unusedScreens.filter { $0.id != id }\n        unusedScreens = filteredScreens\n        debugLog(\"post filter \\(unusedScreens.count)\")\n    }\n\n    // Calculate the size of the global screen (the composite of all the displays attached)\n    func getGlobalScreenRect() -> CGRect {\n        if PrefsDisplays.displayMarginsAdvanced && !advancedMargins.displays.isEmpty, let adv = advancedScreenRect {\n            // Now this is awkward... we precalculated this at detectdisplays->advancedZeroedOrigins\n            return adv\n        } else {\n            var minX: CGFloat = 0.0, minY: CGFloat = 0.0, maxX: CGFloat = 0.0, maxY: CGFloat = 0.0\n            for screen in screens {\n                if screen.bottomLeftFrame.origin.x < minX {\n                    minX = screen.bottomLeftFrame.origin.x\n                }\n                if screen.bottomLeftFrame.origin.y < minY {\n                    minY = screen.bottomLeftFrame.origin.y\n                }\n                if screen.topRightCorner.x > maxX {\n                    maxX = screen.topRightCorner.x\n                }\n                if screen.topRightCorner.y > maxY {\n                    maxY = screen.topRightCorner.y\n                }\n            }\n\n            return CGRect(x: minX, y: minY, width: maxX-minX+(maxLeftScreens*leftMargin()), height: maxY-minY+(maxBelowScreens*belowMargin()))\n        }\n    }\n\n    func getIntermediateAdvancedScreenRect() -> CGRect {\n        // At this point, this is non zeroed\n        var minX: CGFloat = 0.0, minY: CGFloat = 0.0, maxX: CGFloat = 0.0, maxY: CGFloat = 0.0\n        for screen in screens {\n            if screen.zeroedOrigin.x < minX {\n                minX = screen.zeroedOrigin.x\n            }\n            if screen.zeroedOrigin.y < minY {\n                minY = screen.zeroedOrigin.y\n            }\n            if (screen.zeroedOrigin.x + CGFloat(screen.width)) > maxX {\n                maxX = screen.zeroedOrigin.x + CGFloat(screen.width)\n            }\n            if (screen.zeroedOrigin.y + CGFloat(screen.height)) > maxY {\n                maxY = screen.zeroedOrigin.y + CGFloat(screen.height)\n            }\n        }\n\n        return CGRect(x: minX, y: minY, width: maxX-minX, height: maxY-minY)\n    }\n\n    func getZeroedActiveSpannedRect() -> CGRect {\n        if PrefsDisplays.displayMarginsAdvanced && !advancedMargins.displays.isEmpty, let advz = advancedZeroedScreenRect {\n            // Now this is awkward... we precalculated this at detectdisplays->advancedZeroedOrigins\n            return advz\n        } else {\n            var minX: CGFloat = 0.0, minY: CGFloat = 0.0, maxX: CGFloat = 0.0, maxY: CGFloat = 0.0\n            for screen in screens where isScreenActive(id: screen.id) {\n                if screen.bottomLeftFrame.origin.x < minX {\n                    minX = screen.bottomLeftFrame.origin.x\n                }\n                if screen.bottomLeftFrame.origin.y < minY {\n                    minY = screen.bottomLeftFrame.origin.y\n                }\n                if screen.topRightCorner.x > maxX {\n                    maxX = screen.topRightCorner.x\n                }\n                if screen.topRightCorner.y > maxY {\n                    maxY = screen.topRightCorner.y\n                }\n            }\n\n            let width = maxX - minX\n            let height = maxY - minY\n            // Zero the origin to the global rect\n            let orect = getGlobalScreenRect()\n            minX -= orect.origin.x\n            minY -= orect.origin.y\n            return CGRect(x: minX, y: minY, width: width+(maxLeftScreens*leftMargin()), height: height+(maxBelowScreens*belowMargin()))\n        }\n    }\n\n    // NSScreen coordinates are with a bottom left origin, whereas CGDisplay\n    // coordinates are top left origin, this function converts the origin.y value\n    func convertTopLeftToBottomLeft(rect: CGRect) -> CGRect {\n        let screenFrame = (NSScreen.main?.frame)!\n        let newY = 0 - (rect.origin.y - screenFrame.size.height + rect.height)\n        return CGRect(x: rect.origin.x, y: newY, width: rect.width, height: rect.height)\n    }\n\n    // MARK: - Public utility fuctions\n\n    func isScreenActive(id: CGDirectDisplayID) -> Bool {\n        let screen = findScreenWith(id: id)\n        debugLog(\"ISA : \\(screen)\")\n        \n        switch PrefsDisplays.displayMode {\n        case .allDisplays:\n            // This one is easy\n            return true\n        case .mainOnly:\n            if let scr = screen {\n                if scr.isMain {\n                    return true\n                }\n            }\n            return false\n        case .secondaryOnly:\n            if getScreenCount() > 1 {\n                if let scr = screen {\n                    if scr.isMain {\n                        return false\n                    }\n                }\n            }\n            return true\n        case .selection:\n            if isScreenSelected(id: id) {\n                return true\n            }\n            return false\n        }\n    }\n\n    func isScreenSelected(id: CGDirectDisplayID) -> Bool {\n        // If we have it in the dictionnary, then return that\n        if PrefsAdvanced.newDisplayDict.keys.contains(String(id)) {\n            return PrefsAdvanced.newDisplayDict[String(id)]!\n        }\n        return false    // Unknown screens will not be considered selected\n    }\n\n    func selectScreen(id: CGDirectDisplayID) {\n        PrefsAdvanced.newDisplayDict[String(id)] = true\n    }\n\n    func unselectScreen(id: CGDirectDisplayID) {\n        PrefsAdvanced.newDisplayDict[String(id)] = false\n    }\n\n    func getMarginsJSON() -> String {\n        var adv: AdvancedMargin\n\n        if !advancedMargins.displays.isEmpty {\n            // If we have something already in preferences, return that\n            adv = advancedMargins\n        } else {\n            // Generate a JSON from current config\n            var marginArray = [DisplayAdvancedMargin]()\n\n            for screen in screens {\n                let zleft = screen.bottomLeftFrame.origin.x\n                let ztop = screen.bottomLeftFrame.origin.y\n\n                let (leftScreens, belowScreens) = detectBorders(forScreen: screen)\n\n                let offsetleft = leftScreens * CGFloat(PrefsDisplays.horizontalMargin)\n                let offsettop = belowScreens * CGFloat(PrefsDisplays.verticalMargin)\n\n                marginArray.append(DisplayAdvancedMargin(zleft: zleft, ztop: ztop, offsetleft: offsetleft, offsettop: offsettop))\n            }\n\n            adv = AdvancedMargin(displays: marginArray)\n        }\n\n        let encoder = JSONEncoder()\n        encoder.outputFormatting = .prettyPrinted\n\n        do {\n            let jsonData = try encoder.encode(adv)\n            if let jsonString = String(data: jsonData, encoding: .utf8) {\n                return jsonString\n            }\n        } catch {\n            errorLog(error.localizedDescription)\n        }\n\n        return \"\"\n    }\n\n    func findDisplayAdvancedMargins(posx: CGFloat, posy: CGFloat) -> DisplayAdvancedMargin? {\n        for display in advancedMargins.displays {\n            if posx == display.zleft && posy == display.ztop {\n                return display\n            }\n        }\n\n        return nil\n    }\n\n    var advancedMargins: AdvancedMargin {\n        get {\n            let jsonString = PrefsDisplays.advancedMargins\n\n            if let jsonData = jsonString.data(using: .utf8) {\n                let decoder = JSONDecoder()\n\n                do {\n                    let adv = try decoder.decode(AdvancedMargin.self, from: jsonData)\n                    return adv\n                } catch {\n                    errorLog(error.localizedDescription)\n                }\n            }\n            return AdvancedMargin(displays: [DisplayAdvancedMargin]())\n        }\n        set {\n            let encoder = JSONEncoder()\n            encoder.outputFormatting = .prettyPrinted\n\n            do {\n                let jsonData = try encoder.encode(newValue)\n                if let jsonString = String(data: jsonData, encoding: .utf8) {\n                    PrefsDisplays.advancedMargins = jsonString\n                }\n            } catch {\n                errorLog(error.localizedDescription)\n            }\n        }\n    }\n}\n\nstruct AdvancedMargin: Codable {\n    let displays: [DisplayAdvancedMargin]\n}\n\nstruct DisplayAdvancedMargin: Codable {\n    var zleft: CGFloat\n    var ztop: CGFloat\n    var offsetleft: CGFloat\n    var offsettop: CGFloat\n}\n"
  },
  {
    "path": "Aerial/Source/Models/Hardware/HardwareDetection.swift",
    "content": "//\n//  HardwareDetection.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 03/06/2019.\n//  Copyright © 2019 John Coates. All rights reserved.\n//\n\n// When available, macOS will use the fixed functions units in Intel CPUs (QuickSync) for hardware\n// decoding of H.264 and H.265, independent of if there's a GPU present.\n// This is an issue as H.265 decoding is only partially supported on some Intel CPUs, up to Kaby Lake\n// generation where they support Main profile decoding, but not Main10 (which is used by Apple's videos).\n//\n// Mode info can be found here : https://github.com/JohnCoates/Aerial/blob/master/Documentation/HardwareDecoding.md\n\nimport Foundation\n\nenum HEVCMain10Support: Int {\n    case notsupported, unsure, partial, supported\n}\n\nfinal class HardwareDetection: NSObject {\n    static let sharedInstance = HardwareDetection()\n\n    // MARK: - Mac Model detection\n\n    private func getMacModel() -> String {\n        var size = 0\n        sysctlbyname(\"hw.model\", nil, &size, nil, 0)\n        var machine = [CChar](repeating: 0, count: size)\n        sysctlbyname(\"hw.model\", &machine, &size, nil, 0)\n        return String(cString: machine)\n    }\n\n    private func extractMacVersion(macModel: String, macSubmodel: String) -> Double {\n        // Substring the thing\n        let str = String(macModel.dropFirst(macSubmodel.count))\n        let formatter = NumberFormatter()\n        formatter.locale = Locale(identifier: \"fr_FR\")\n        return formatter.number(from: str)?.doubleValue ?? 0.0\n    }\n\n    // Get best suggestion\n    // swiftlint:disable:next cyclomatic_complexity\n    func getSuggestedFormat() -> VideoFormat {\n        switch isHEVCMain10HWDecodingAvailable() {\n        case .supported:\n            if #available(OSX 10.15, *) {\n                return .v4KHDR\n            } else {\n                // That was a fun one to track...\n                return .v4KHEVC\n            }\n        case .notsupported:\n            return .v1080pH264\n        case .partial:\n            // This is tricky\n            let macModel = getMacModel()\n\n            if macModel.starts(with: \"iMac\") {\n                // iMacs, as far as we know, partial 17+, full 18+\n                let ver = extractMacVersion(macModel: macModel, macSubmodel: \"iMac\")\n                if ver >= 17.0 {\n                    return .v4KHEVC\n                } else {\n                    return .v1080pH264\n                }\n            } else if macModel.starts(with: \"MacBookPro\") {\n                let ver = extractMacVersion(macModel: macModel, macSubmodel: \"MacBookPro\")\n                // MacBookPro full 14+\n                if ver >= 17.0 {\n                    return .v1080pHEVC\n                } else {\n                    return .v1080pH264\n                }\n            } else if macModel.starts(with: \"MacBookAir\") {\n                // Retina 8+, I *think* they handle main10\n                return .v1080pH264\n            } else if macModel.starts(with: \"MacBook\") {\n                // MacBook 10+\n                return .v1080pH264\n            }\n\n            return .v1080pH264\n        case .unsure:\n            // Eh\n            return .v1080pH264\n        }\n    }\n\n    // MARK: - HEVC Main10 detection\n\n    func isHEVCMain10HWDecodingAvailable() -> HEVCMain10Support {\n        let macModel = getMacModel()\n\n        // Apple silicon supports everything!\n        if isAppleSilicon() {\n            return .supported\n        }\n            \n        // This is a manually compiled list based on CPU generations of each mac model line\n        if macModel.starts(with: \"iMacPro\") || macModel.starts(with: \"ADP\") {\n            // iMacPro - always\n            return .supported\n        } else if macModel.starts(with: \"iMac\") {\n            // iMacs, as far as we know, partial 17+, full 18+\n            return getHEVCMain10Support(macModel: macModel, macSubmodel: \"iMac\", partial: 17.0, full: 18.0)\n        } else if macModel.starts(with: \"MacBookPro\") {\n            // MacBookPro full 14+\n            return getHEVCMain10Support(macModel: macModel, macSubmodel: \"MacBookPro\", partial: 13.0, full: 14.0)\n        } else if macModel.starts(with: \"MacBookAir\") {\n            // Retina 8+, I *think* they handle main10\n            return getHEVCMain10Support(macModel: macModel, macSubmodel: \"MacBookAir\", partial: 8.0, full: 8.0)\n        } else if macModel.starts(with: \"MacBook\") {\n            // MacBook 10+\n            return getHEVCMain10Support(macModel: macModel, macSubmodel: \"MacBook\", partial: 9.0, full: 10.0)\n        } else if macModel.starts(with: \"Macmini\") {\n            // MacMini 8+\n            return getHEVCMain10Support(macModel: macModel, macSubmodel: \"Macmini\", partial: 8.0, full: 8.0)\n        } else if macModel.starts(with: \"MacPro\") {\n            // Tentative, I *think* 7+ (2019 MacPro) should always support independant of GPU, akin to iMac Pro ?\n            return getHEVCMain10Support(macModel: macModel, macSubmodel: \"MacPro\", partial: 7.0, full: 7.0)\n        }\n\n        // Older stuff (power/etc) should not even run, so list should be complete\n        // Hackintosh/new SKUs will fail this test, this is indicative in any case so that's fine\n        return .unsure\n    }\n\n    // Helper\n    private func getHEVCMain10Support(macModel: String, macSubmodel: String, partial: Double, full: Double) -> HEVCMain10Support {\n        let ver = extractMacVersion(macModel: macModel, macSubmodel: macSubmodel)\n\n        if ver >= full {\n            return .supported\n        } else if ver >= partial {\n            return .partial\n        } else {\n            return .notsupported\n        }\n    }\n    \n    func isAppleSilicon() -> Bool {\n        if #available(macOS 12, *) {\n            var systeminfo = utsname()\n            uname(&systeminfo)\n            let machine = withUnsafeBytes(of: &systeminfo.machine) {bufPtr->String in\n                let data = Data(bufPtr)\n                if let lastIndex = data.lastIndex(where: {$0 != 0}) {\n                    return String(data: data[0...lastIndex], encoding: .isoLatin1)!\n                } else {\n                    return String(data: data, encoding: .isoLatin1)!\n                }\n            }\n            \n            debugLog(machine)\n            return machine != \"x86_64\"\n        } else {\n            return false\n        }\n    }\n\n}\n"
  },
  {
    "path": "Aerial/Source/Models/Hardware/ISSoundAdditions/Sound.swift",
    "content": "//\n//  SoundOutputManager.swift\n//\n//\n//  Created by Alessio Moiso on 08.03.22.\n//\n\n/// Entry point to access and modify the system sound settings, such\n/// muting/unmuting and changing the volume.\n///\n/// # Overview\n/// This class cannot be instantiated, but you can interact with its `output` property directly.\n/// You can use the shared instance to change the output volume as well as\n/// mute and unmute.\npublic enum Sound {\n  static let output = SoundOutputManager()\n}\n"
  },
  {
    "path": "Aerial/Source/Models/Hardware/ISSoundAdditions/SoundOutputManager+Goodies.swift",
    "content": "//\n//  File.swift\n//  \n//\n//  Created by Alessio Moiso on 09.03.22.\n//\n\npublic extension Sound.SoundOutputManager {\n  /// Increase the volume of the default output device\n  /// by the given amount.\n  ///\n  /// Errors will be ignored.\n  ///\n  /// The values range between 0 and 1. If the increase results\n  /// in a value outside of the bounds, it will be normalized to the closest\n  /// value in the bounds.\n  func increaseVolume(by value: Float, autoMuteUnmute: Bool = false, muteThreshold: Float = 0.005) {\n    setVolume(volume+value, autoMuteUnmute: autoMuteUnmute, muteThreshold: muteThreshold)\n  }\n  \n  /// Decrease the volume of the default output device\n  /// by the given amount.\n  ///\n  /// Errors will be ignored.\n  ///\n  /// The values range between 0 and 1. If the decrease results\n  /// in a value outside of the bounds, it will be normalized to the closest\n  /// value in the bounds.\n  func decreaseVolume(by value: Float, autoMuteUnmute: Bool = false, muteThreshold: Float = 0.005) {\n    setVolume(volume-value, autoMuteUnmute: autoMuteUnmute, muteThreshold: muteThreshold)\n  }\n  \n  /// Set the volume of the default output device and,\n  /// if lower or higher then `muteThreshold` also toggles the mute property.\n  ///\n  /// - warning: This function will unmute a muted device, if the volume is greater\n  /// then `muteThreshold`. Please, make sure that the user is aware of this and always\n  /// respect the Do Not Disturb modes and other system settings.\n  ///\n  /// - parameters:\n  ///   - newValue: The volume.\n  ///   - autoMuteUnmute: If `true`, will use the `muteThreshold` to determine whether the device\n  ///   should also be muted or unmuted.\n  ///   - muteThreshold: Defines the threshold that should cause an automatic mute for all values below it.\n  func setVolume(_ newValue: Float, autoMuteUnmute: Bool, muteThreshold: Float = 0.005) {\n    volume = newValue\n    guard autoMuteUnmute else { return }\n    isMuted = newValue <= muteThreshold\n  }\n}\n"
  },
  {
    "path": "Aerial/Source/Models/Hardware/ISSoundAdditions/SoundOutputManager+Properties.swift",
    "content": "//\n//  SoundOutputManager+Properties.swift\n//  \n//\n//  Created by Alessio Moiso on 09.03.22.\n//\nimport CoreAudio\n\npublic extension Sound.SoundOutputManager {\n  /// Get the system default output device.\n  ///\n  /// You can use this value to interact with the device directly via\n  /// other system calls.\n  ///\n  /// This value will return `nil` if there is currently no device selected in\n  /// System Preferences > Sound > Output.\n  var defaultOutputDevice: AudioDeviceID? {\n    try? retrieveDefaultOutputDevice()\n  }\n  \n  /// Get or set the volume of the default output device.\n  ///\n  /// Errors will be ignored. If you need to handle errors,\n  /// use `readVolume` and `setVolume`.\n  ///\n  /// The values range between 0 and 1.\n  var volume: Float {\n    get {\n      (try? readVolume()) ?? 0\n    }\n    set {\n      do {\n        try setVolume(newValue)\n      } catch { }\n    }\n  }\n  \n  /// Get or set whether the system default output device is muted or not.\n  ///\n  /// Errors will be ignored. If you need to handle errors,\n  /// use `readMute` and `mute`. Devices that do not support muting\n  /// will always return `false`.\n  var isMuted: Bool {\n    get {\n      (try? readMute()) ?? false\n    }\n    set {\n      do {\n        try mute(newValue)\n      } catch { }\n    }\n  }\n}\n"
  },
  {
    "path": "Aerial/Source/Models/Hardware/ISSoundAdditions/SoundOutputManager.swift",
    "content": "//\n//  SoundOutputManager.swift\n//  \n//\n//  Created by Alessio Moiso on 08.03.22.\n//\n\nimport CoreAudio\nimport AudioToolbox\nimport Cocoa\n\nextension Sound {\n  /// Mute, unmute and change the volume of the system default output device.\n  ///\n  /// # Overview\n  /// You can interact with this class in two ways:\n  /// - you can interact with its properties, meaning that all changes\n  /// will be applied immediately and errors will be hidden.\n  /// - you can call its methods and handle errors manually.\n  public final class SoundOutputManager {\n    /// All the possible errors that could occur while interacting\n    /// with the default output device.\n    enum Errors: Error {\n            /// The system couldn't complete the requested operation and\n            /// returned the given status.\n      case  operationFailed(OSStatus)\n            /// The current default output device doesn't support the requested property.\n      case  unsupportedProperty\n            /// The current default output device doesn't allow changing the requested property.\n      case  immutableProperty\n            /// There is no default output device.\n      case  noDevice\n    }\n    \n    internal init() { }\n    \n    /// Get the system default output device.\n    ///\n    /// You can use this value to interact with the device directly\n    /// via other system calls.\n    ///\n    /// - throws: `Errors.operationFailed` if the system fails to return the default output device.\n    /// - returns: the default device ID or `nil` if none is set.\n    public func retrieveDefaultOutputDevice() throws -> AudioDeviceID? {\n      var result = kAudioObjectUnknown\n      var size = UInt32(MemoryLayout<AudioDeviceID>.size)\n      var address = AudioObjectPropertyAddress(\n        mSelector: kAudioHardwarePropertyDefaultOutputDevice,\n        mScope: kAudioObjectPropertyScopeGlobal,\n        mElement: kAudioObjectPropertyElementMain\n      )\n      \n      // Ensure that a default device exists.\n      guard AudioObjectHasProperty(AudioObjectID(kAudioObjectSystemObject), &address) else { return nil }\n      \n      // Attempt to get the default output device.\n      let error = AudioObjectGetPropertyData(AudioObjectID(kAudioObjectSystemObject), &address, 0, nil, &size, &result)\n      guard error == noErr else {\n        throw Errors.operationFailed(error)\n      }\n      \n      if result == kAudioObjectUnknown {\n        throw Errors.noDevice\n      }\n      \n      return result\n    }\n    \n    /// Get the volume of the system default output device.\n    ///\n    /// - throws: `Errors.noDevice` if the system doesn't have a default output device; `Errors.unsupportedProperty` if the current device doesn't have a volume property; `Errors.operationFailed` if the system is unable to read the property value.\n    /// - returns: The current volume in a range between 0 and 1.\n    public func readVolume() throws -> Float {\n      guard let deviceID = try retrieveDefaultOutputDevice() else {\n        throw Errors.noDevice\n      }\n      \n      var size = UInt32(MemoryLayout<Float32>.size)\n      var volume: Float = 0\n      var address = AudioObjectPropertyAddress(\n        mSelector: kAudioHardwareServiceDeviceProperty_VirtualMainVolume,\n        mScope: kAudioDevicePropertyScopeOutput,\n        mElement: kAudioObjectPropertyElementMain\n      )\n      \n      // Ensure the device has a volume property.\n      guard AudioObjectHasProperty(deviceID, &address) else {\n        throw Errors.unsupportedProperty\n      }\n      \n      let error = AudioObjectGetPropertyData(deviceID, &address, 0, nil, &size, &volume)\n      guard error == noErr else {\n        throw Errors.operationFailed(error)\n      }\n      \n      return min(max(0, volume), 1)\n    }\n    \n    /// Set the volume of the system default output device.\n    ///\n    /// - parameter newValue: The volume to set in a range between 0 and 1.\n    /// - throws: `Erors.noDevice` if the system doesn't have a default output device; `Errors.unsupportedProperty` or `Errors.immutableProperty` if the output device doesn't support setting or doesn't currently allow changes to its volume; `Errors.operationFailed` if the system is unable to apply the volume change.\n    public func setVolume(_ newValue: Float) throws {\n      guard let deviceID = try retrieveDefaultOutputDevice() else {\n        throw Errors.noDevice\n      }\n      \n      var normalizedValue = min(max(0, newValue), 1)\n      var address = AudioObjectPropertyAddress(\n        mSelector: kAudioHardwareServiceDeviceProperty_VirtualMainVolume,\n        mScope: kAudioDevicePropertyScopeOutput,\n        mElement: kAudioObjectPropertyElementMain\n      )\n      \n      // Ensure the device has a volume property.\n      guard AudioObjectHasProperty(deviceID, &address) else {\n        throw Errors.unsupportedProperty\n      }\n      \n      var canChangeVolume = DarwinBoolean(true)\n      let size = UInt32(MemoryLayout<Float>.size(ofValue: normalizedValue))\n      let isSettableError = AudioObjectIsPropertySettable(deviceID, &address, &canChangeVolume)\n      \n      // Ensure the volume property is editable.\n      guard isSettableError == noErr else {\n        throw Errors.operationFailed(isSettableError)\n      }\n      guard canChangeVolume.boolValue else {\n        throw Errors.immutableProperty\n      }\n      \n      let error = AudioObjectSetPropertyData(deviceID, &address, 0, nil, size, &normalizedValue)\n      \n      if error != noErr {\n        throw Errors.operationFailed(error)\n      }\n    }\n    \n    /// Get whether the system default output device is currently muted or not.\n    ///\n    /// - throws: `Errors.noDevice` if the system doesn't have a default output device;\n    /// `Errors.unsupportedProperty` if the current device doesn't have a mute property;\n    /// `Errors.operationFailed` if the system is unable to read the property value.\n    /// - returns: Whether the device is muted or not.\n    public func readMute() throws -> Bool {\n      guard let deviceID = try retrieveDefaultOutputDevice() else {\n        throw Errors.noDevice\n      }\n      \n      var isMuted: UInt32 = 0\n      var size = UInt32(MemoryLayout<UInt32>.size(ofValue: isMuted))\n      var address = AudioObjectPropertyAddress(\n        mSelector: kAudioDevicePropertyMute,\n        mScope: kAudioDevicePropertyScopeOutput,\n        mElement: kAudioObjectPropertyElementMain\n      )\n      \n      // Ensure the device supports the option to be muted.\n      guard AudioObjectHasProperty(deviceID, &address) else {\n        throw Errors.unsupportedProperty\n      }\n      \n      let error = AudioObjectGetPropertyData(deviceID, &address, 0, nil, &size, &isMuted)\n      \n      guard error == noErr else {\n        throw Errors.operationFailed(error)\n      }\n      \n      return isMuted == 1\n    }\n    \n    /// Mute or unmute the system default output device.\n    ///\n    /// - parameter isMuted: Mute or unmute.\n    /// - throws: `Errors.noDevice` if the system doesn't have a default output device;\n    /// `Errors.unsupportedProperty` or `Errors.immutableProperty` if the output device doesn't\n    /// support setting or doesn't currently allow changes to its mute property; `Errors.operationFailed`\n    /// if the system is unable to apply the change.\n    public func mute(_ isMuted: Bool) throws {\n      guard let deviceID = try retrieveDefaultOutputDevice() else {\n        throw Errors.noDevice\n      }\n      \n      var normalizedValue: UInt = isMuted ? 1 : 0\n      var address = AudioObjectPropertyAddress(\n        mSelector: kAudioDevicePropertyMute,\n        mScope: kAudioDevicePropertyScopeOutput,\n        mElement: kAudioObjectPropertyElementMain\n      )\n      \n      // Ensure the device supports the option to be muted.\n      guard AudioObjectHasProperty(deviceID, &address) else {\n        throw Errors.unsupportedProperty\n      }\n      \n      var canMute = DarwinBoolean(true)\n      let size = UInt32(MemoryLayout<UInt>.size(ofValue: normalizedValue))\n      let isSettableError = AudioObjectIsPropertySettable(deviceID, &address, &canMute)\n      \n      // Ensure that the mute property is editable.\n      guard isSettableError == noErr, canMute.boolValue else {\n        throw Errors.immutableProperty\n      }\n      \n      let error = AudioObjectSetPropertyData(deviceID, &address, 0, nil, size, &normalizedValue)\n      \n      if error != noErr {\n        throw Errors.operationFailed(error)\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "Aerial/Source/Models/Hardware/NightShift.swift",
    "content": "//\n//  NightShift.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 19/12/2019.\n//  Copyright © 2019 Guillaume Louel. All rights reserved.\n//\n\nimport Foundation\n\nstruct NightShift {\n\n    static var isNightShiftDataCached = false\n    static var nightShiftAvailable = false\n    static var nightShiftSunrise = Date()\n    static var nightShiftSunset = Date()\n\n    // MARK: Night Shift\n    static func isAvailable() -> (Bool, reason: String) {\n        if #available(OSX 10.12.4, *) {\n            let (isAvailable, sunriseDate, sunsetDate, errorMessage) = NightShift.getInformation()\n\n            if isAvailable {\n                let dateFormatter = DateFormatter()\n                dateFormatter.dateFormat = DateFormatter.dateFormat(fromTemplate: \"j:mm:ss\", options: 0, locale: Locale.current)\n                let sunriseString = dateFormatter.string(from: sunriseDate!)\n                let sunsetString = dateFormatter.string(from: sunsetDate!)\n\n                return (true, \"Today’s sunrise: \" + sunriseString + \"  Today’s sunset: \" + sunsetString)\n\n            } else {\n                isNightShiftDataCached = true\n                return (false, errorMessage!)\n            }\n        } else {\n            return (false, \"macOS 10.12.4 or above is required\")\n        }\n    }\n\n    // swiftlint:disable:next large_tuple\n    static func getInformation() -> (Bool, sunrise: Date?, sunset: Date?, error: String?) {\n        // Sonoma workaround\n        if !Aerial.helper.underCompanion {\n            if #available(macOS 14.0, *) {\n                if CompanionBridge.nightShiftSunrise != nil {\n                    debugLog(\"Nightshift using CompanionBridge data\")\n                    return (true, CompanionBridge.nightShiftSunrise, CompanionBridge.nightShiftSunset, nil)\n                } else {\n                    return (false, nil, nil, \"Sonoma requires Aerial Companion\")\n                }\n            }\n        }\n        if isNightShiftDataCached {\n            return (nightShiftAvailable, nightShiftSunrise, nightShiftSunset, nil)\n        }\n\n        // On Catalina, corebrightnessdiag was moved to /usr/libexec/ !\n        var cbdpath = \"/usr/bin/corebrightnessdiag\"\n        if #available(OSX 10.15, *) {\n            cbdpath = \"/usr/libexec/corebrightnessdiag\"\n        }\n\n        let (nsInfo, ts) = Aerial.helper.shell(launchPath: cbdpath, arguments: [\"nightshift-internal\"])\n        \n\n        if ts != 0 {\n            // Task didn't return correctly ? Abort\n            return (false, nil, nil, \"Your Mac does not support Night Shift\")\n        }\n        let lines = nsInfo?.split(separator: \"\\n\")\n        if lines!.count < 5 {\n            // We get a couple of lines of output on unsupported Macs\n            return (false, nil, nil, \"Your Mac does not support Night Shift\")\n        }\n        var sunrise: Date?, sunset: Date?\n\n        for line in lines ?? [\"\"] {\n            if line.contains(\"sunrise\") {\n                if let gdate = getDateFromLine(String(line)) {\n                    sunrise = gdate\n                }\n            } else if line.contains(\"sunset\") {\n                if let gdate = getDateFromLine(String(line)) {\n                    sunset = gdate\n                }\n            }\n        }\n\n        if sunset != nil && sunrise != nil {\n            nightShiftSunrise = sunrise!\n            nightShiftSunset = sunset!\n            nightShiftAvailable = true\n            isNightShiftDataCached = true\n\n            return (true, sunrise, sunset, nil)\n        }\n\n        // /usr/bin/corebrightnessdiag nightshift-internal | grep nextSunset | cut -d \\\" -f2\n        warnLog(\"Location services may be disabled, Night Shift can't detect Sunrise and Sunset times without them\")\n        return (false, nil, nil, \"Location services may be disabled\")\n    }\n\n    // Helpers\n    private static func getDateFromLine(_ line: String) -> Date? {\n        let tmp = line.split(separator: \"\\\"\")\n\n        if tmp.count > 1 {\n            let dateFormatter = DateFormatter()\n            dateFormatter.dateFormat = \"yyyy-MM-dd HH:mm:ss ZZZ\"\n\n            if let dateObj = dateFormatter.date(from: String(tmp[1])) {\n                return dateObj\n            }\n        }\n\n        return nil\n    }\n\n}\n"
  },
  {
    "path": "Aerial/Source/Models/Locations.swift",
    "content": "//\n//  Location.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 24/05/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Foundation\nimport CoreLocation\n\nclass Locations: NSObject {\n    static let sharedInstance = Locations()\n    let locationManager = CLLocationManager()\n    var coordinates: CLLocationCoordinate2D?\n    var failures: [(String) -> Void] = []\n    var successes: [(CLLocationCoordinate2D) -> Void] = []\n\n    // MARK: - Lifecycle\n    override init() {\n        super.init()\n        locationManager.delegate = self\n        debugLog(\"Starting Location initialization\")\n    }\n\n    func getCoordinates(failure: @escaping (_ error: String) -> Void,\n                        success: @escaping (_ response: CLLocationCoordinate2D) -> Void) {\n        // Sonoma workaround via CompanionBridge\n        if !Aerial.helper.underCompanion {\n            if #available(macOS 14.0, *) {\n                if CompanionBridge.locationLat != nil && CompanionBridge.locationLong != nil {\n                    debugLog(\"Location using CompanionBridge data\")\n                    \n                    let coords = CLLocationCoordinate2DMake(\n                        CompanionBridge.locationLat! as CLLocationDegrees,\n                        CompanionBridge.locationLong! as CLLocationDegrees)\n\n                    success(coords)\n                    return\n                }\n            }\n        }\n        \n        // Perhaps they are cached already ?\n        if coordinates != nil {\n            debugLog(\"Location using cached data\")\n            success(coordinates!)\n            return\n        }\n\n        // Check for access & start\n        if CLLocationManager.locationServicesEnabled() {\n            debugLog(\"Location services enabled\")\n            locationManager.startUpdatingLocation()\n        } else {\n            debugLog(\"Location services disabled\")\n\n            if PrefsTime.cachedLatitude != 0 {\n                debugLog(\"Couldn't retrieve your location, using latest cached coordinates instead\")\n                // Read them\n                coordinates = CLLocationCoordinate2DMake(\n                    PrefsTime.cachedLatitude as CLLocationDegrees,\n                    PrefsTime.cachedLongitude as CLLocationDegrees)\n\n                // Pretend we didn't fail\n                success(coordinates!)\n            } else {\n                debugLog(\"No cached coordinates\")\n                failure(\"Location services disabled\")\n            }\n        }\n\n        // This seems super wrong...\n        if #available(OSX 10.14, *) {\n            // Add our callbacks, as this is the only time we'll really defer\n            failures.append(failure)\n            successes.append(success)\n\n            locationManager.requestLocation()\n        } else {\n            // Fallback on earlier versions\n            failure(\"macOS 10.14 is required\")\n        }\n    }\n}\n\nextension Locations: CLLocationManagerDelegate {\n    // Auth status callback\n    func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {\n        debugLog(\"LMauth status change : \\(status.rawValue)\")\n        if status == .denied {\n            if PrefsTime.cachedLatitude != 0 {\n                debugLog(\"Couldn't retrieve your location, using latest cached coordinates instead\")\n                // Read them\n                coordinates = CLLocationCoordinate2DMake(\n                    PrefsTime.cachedLatitude as CLLocationDegrees,\n                    PrefsTime.cachedLongitude as CLLocationDegrees)\n\n                // Pretend we didn't fail\n                for success in successes {\n                    success(coordinates!)\n                }\n\n                // Then cleanup\n                successes.removeAll()\n                failures.removeAll()\n            } else {\n                debugLog(\"Location services are either globally disabled, or disabled for Aerial. Please enable them at least once so Aerial can get your coordinates, or use another Time management mode.\")\n            }\n        }\n    }\n\n    // Location fetch Success callback\n    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {\n        let currentLocation = locations[locations.count - 1]\n        coordinates = currentLocation.coordinate    // Wondering, why singular?\n        debugLog(\"Location coordinate : \\(currentLocation.coordinate)\")\n        locationManager.stopUpdatingLocation()      // We only want them once\n\n        // We cache for next time if we are WiFi-less\n        PrefsTime.cachedLatitude = coordinates?.latitude ?? 0\n        PrefsTime.cachedLongitude = coordinates?.longitude ?? 0\n\n        for success in successes {\n            success(currentLocation.coordinate)\n        }\n        successes.removeAll()\n        failures.removeAll()\n    }\n\n    // Location fetch Failure callback\n    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {\n        // So we failed, but maybe we have something cached to pretent we didn't fail\n        if PrefsTime.cachedLatitude != 0 {\n            debugLog(\"Couldn't retrieve your location: \\(error.localizedDescription), using latest cached coordinates instead\")\n            // Store them\n            coordinates = CLLocationCoordinate2DMake(PrefsTime.cachedLatitude as CLLocationDegrees, PrefsTime.cachedLongitude as CLLocationDegrees)\n\n            // Pretend we didn't fail\n            for success in successes {\n                success(coordinates!)\n            }\n        } else {\n            // This is a total failure\n            for failure in failures {\n                failure(\"Unable to fetch location\")\n            }\n        }\n\n        // Then cleanup\n        successes.removeAll()\n        failures.removeAll()\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Models/ManifestLoader.swift",
    "content": "//\n//  ManifestLoader.swift\n//  Aerial\n//  WARNING : This is the old deprecated stuff\n//\n//  Created by John Coates on 10/28/15.\n//  Copyright © 2015 John Coates. All rights reserved.\n//\n\nimport Foundation\nimport ScreenSaver\nimport GameplayKit\nimport AVFoundation\n\ntypealias ManifestLoadCallback = ([AerialVideo]) -> Void\n\n// swiftlint:disable:next type_body_length\nclass ManifestLoader {\n    static let instance: ManifestLoader = ManifestLoader()\n\n    var callbacks = [ManifestLoadCallback]()\n    var loadedManifest = [AerialVideo]()\n    var processedVideos = [AerialVideo]()\n    var lastPluckedFromPlaylist: AerialVideo?\n    var customVideoFolders: CustomVideoFolders?\n\n    var manifestTvOS10: Data?\n    var manifestTvOS11: Data?\n    var manifestTvOS12: Data?\n    var manifestTvOS13: Data?\n\n    // Playlist management\n    var playlistIsRestricted = false\n    var playlistRestrictedTo = \"\"\n    var playlist = [AerialVideo]()\n\n    // Those videos will be ignored\n    let blacklist = [\"b10-1.mov\",           // Dupe of b1-1 (Hawaii, day)\n                     \"b10-2.mov\",           // Dupe of b2-3 (New York, night)\n                     \"b10-4.mov\",           // Dupe of b2-4 (San Francisco, night)\n                     \"b9-1.mov\",            // Dupe of b2-2 (Hawaii, day)\n                     \"b9-2.mov\",            // Dupe of b3-1 (London, night)\n                     \"comp_LA_A005_C009_v05_t9_6M.mov\",     // Low quality version of Los Angeles day 687B36CB-BA5D-4434-BA99-2F2B8B6EC163\n                     \"comp_LA_A009_C009_t9_6M_tag0.mov\"\n                     ]    // Low quality version of Los Angeles night 89B1643B-06DD-4DEC-B1B0-774493B0F7B7\n\n    // This is used for videos where URLs should be merged with different ID\n    // This is used to dedupe old versions of videos\n    // old : new\n    let dupePairs = [\n        \"A2BE2E4A-AD4B-428A-9C41-BDAE1E78E816\": \"12318CCB-3F78-43B7-A854-EFDCCE5312CD\",     // California to Vegas (v7 -> v8)\n        \"6A74D52E-2447-4B84-AE45-0DEF2836C3CC\": \"7825C73A-658F-48EE-B14C-EC56673094AC\",     // China\n        \"6C3D54AE-0871-498A-81D0-56ED24E5FE9F\": \"009BA758-7060-4479-8EE8-FB9B40C8FB97\",     // Korean and Japan night\n        \"b5-1\": \"044AD56C-A107-41B2-90CC-E60CCACFBCF5\",                                     // Great Wall 3\n        \"b2-1\": \"22162A9B-DB90-4517-867C-C676BC3E8E95\",                                     // Great wall 2\n        \"b6-1\": \"F0236EC5-EE72-4058-A6CE-1F7D2E8253BF\",                                     // Great wall 1\n        \"BAF76353-3475-4855-B7E1-CE96CC9BC3A7\": \"9680B8EB-CE2A-4395-AF41-402801F4D6A6\",     // Approaching Burj Khalifa (night)\n        \"B3BDC635-756D-4B82-B01A-A2620D1DBF10\": \"9680B8EB-CE2A-4395-AF41-402801F4D6A6\",     // Approaching Burj Khalifa (night)\n        \"15F9B681-9EA8-4DD1-AD26-F111BC5CF64B\": \"E991AC0C-F272-44D8-88F3-05F44EDFE3AE\",     // Marina 1\n        \"49790B7C-7D8C-466C-A09E-83E38B6BE87A\": \"E991AC0C-F272-44D8-88F3-05F44EDFE3AE\",     // Marina 1\n        \"802866E6-4AAF-4A69-96EA-C582651391F1\": \"3FFA2A97-7D28-49EA-AA39-5BC9051B2745\",     // Marina 2\n        \"D34A7B19-EC33-4300-B4ED-0C8BC494C035\": \"3FFA2A97-7D28-49EA-AA39-5BC9051B2745\",     // Marina 2\n        \"02EA5DBE-3A67-4DFA-8528-12901DFD6CC1\": \"00BA71CD-2C54-415A-A68A-8358E677D750\",     // Downtown\n        \"AC9C09DD-1D97-4013-A09F-B0F5259E64C3\": \"876D51F4-3D78-4221-8AD2-F9E78C0FD9B9\",     // Sheikh Zayed Road (day)\n        \"DFA399FA-620A-4517-94D6-BF78BF8C5E5A\": \"876D51F4-3D78-4221-8AD2-F9E78C0FD9B9\",     // Sheikh Zayed Road (day)\n        \"D388F00A-5A32-4431-A95C-38BF7FF7268D\": \"B8F204CE-6024-49AB-85F9-7CA2F6DCD226\",     // Nuusuaq Peninsula\n        \"E4ED0B22-EB81-4D4F-A29E-7E1EA6B6D980\": \"B8F204CE-6024-49AB-85F9-7CA2F6DCD226\",     // Nuusuaq Peninsula\n        \"30047FDA-3AE3-4E74-9575-3520AD77865B\": \"2F52E34C-39D4-4AB1-9025-8F7141FAA720\",     // Ilulissat Icefjord day\n        \"7D4710EB-5BA4-42E6-AA60-68D77F67D9B9\": \"EE01F02D-1413-436C-AB05-410F224A5B7B\",     // Ilulissat Icefjord Night\n        \"b8-1\": \"82BD33C9-B6D2-47E7-9C42-AA3B7758921A\",                                     // Pu'u O 'Umi Night\n        \"b4-1\": \"258A6797-CC13-4C3A-AB35-4F25CA3BF474\",                                     // Pu'u O 'Umi day\n        \"b1-1\": \"12E0343D-2CD9-48EA-AB57-4D680FB6D0C7\",                                     // Waimanu Valley\n        \"b7-1\": \"499995FA-E51A-4ACE-8DFD-BDF8AFF6C943\",                                     // Laupāhoehoe Nui\n        \"b6-2\": \"3D729CFC-9000-48D3-A052-C5BD5B7A6842\",                                     // Kohala coastline\n        \"30313BC1-BF20-45EB-A7B1-5A6FFDBD2488\": \"E99FA658-A59A-4A2D-9F3B-58E7BDC71A9A\",     // Hong Kong Victoria Harbour night\n        \"2A57BB93-1825-484C-9609-FF8580CAE77B\": \"E99FA658-A59A-4A2D-9F3B-58E7BDC71A9A\",     // Hong Kong Victoria Harbour night\n        \"102C19D1-9D9F-48EC-B492-074C985C4D9F\": \"FE8E1F9D-59BA-4207-B626-28E34D810D0A\",     // Hong Kong Victoria Harbour 1\n        \"786E674C-BB22-4AA9-9BD3-114D2020EC4D\": \"64EA30BD-C4B5-4CDD-86D7-DFE47E9CB9AA\",     // Hong Kong Victoria Harbour 2\n        \"560E09E8-E89D-4ADB-8EEA-4754415383D4\": \"C8559883-6F3E-4AF2-8960-903710CD47B7\",     // Hong Kong Victoria Peak\n        \"6E2FC8AC-832D-46CF-B306-BB2A05030C17\": \"001C94AE-2BA4-4E77-A202-F7DE60E8B1C8\",     // Liwa oasis 1\n        \"88025454-6D58-48E8-A2DB-924988FAD7AC\": \"001C94AE-2BA4-4E77-A202-F7DE60E8B1C8\",     // Liwa oasis 1\n        \"b6-3\": \"58754319-8709-4AB0-8674-B34F04E7FFE2\",                                     // River Thames\n        \"b1-2\": \"F604AF56-EA77-4960-AEF7-82533CC1A8B3\",                                     // River Thames near sunset\n        \"b3-1\": \"7F4C26C2-67C2-4C3A-8F07-8A7BF6148C97\",                                     // River Times at Dusk\n        \"b5-2\": \"A5AAFF5D-8887-42BB-8AFD-867EF557ED85\",                                     // Buckingham Palace\n        \"BEED64EC-2DB7-47E1-A67E-59C101E73C04\": \"CE279831-1CA7-4A83-A97B-FF1E20234396\",     // LAX\n        \"829E69BA-BB53-4841-A138-4DF0C2A74236\": \"CE279831-1CA7-4A83-A97B-FF1E20234396\",     // LAX\n        \"60CD8E2E-35CD-4192-A5A4-D5E10BFE158B\": \"92E48DE9-13A1-4172-B560-29B4668A87EE\",     // Santa Monica Beach\n        \"B730433D-1B3B-4B99-9500-A286BF7A9940\": \"92E48DE9-13A1-4172-B560-29B4668A87EE\",     // Santa Monica Beach\n        \"30A2A488-E708-42E7-9A90-B749A407AE1C\": \"35693AEA-F8C4-4A80-B77D-C94B20A68956\",     // Harbor Freeway\n        \"A284F0BF-E690-4C13-92E2-4672D93E8DE5\": \"F5804DD6-5963-40DA-9FA0-39C0C6E6DEF9\",     // Downtown\n        \"b3-2\": \"840FE8E4-D952-4680-B1A7-AC5BACA2C1F8\",                                     // Upper East side\n        \"b4-2\": \"640DFB00-FBB9-45DA-9444-9F663859F4BC\",                                     // Lower Manhattan (night)\n        \"b2-3\": \"44166C39-8566-4ECA-BD16-43159429B52F\",                                     // Seventh Avenue\n        \"b7-2\": \"3BA0CFC7-E460-4B59-A817-B97F9EBB9B89\",                                     // Central Park\n        \"b10-3\": \"EE533FBD-90AE-419A-AD13-D7A60E2015D6\",                                    // Marin Headlands in Fog\n        \"b1-4\": \"3E94AE98-EAF2-4B09-96E3-452F46BC114E\",                                     // Bay bridge night\n        \"b9-3\": \"DE851E6D-C2BE-4D9F-AB54-0F9CE994DC51\",                                     // Bay and Golden Bridge\n        \"b7-3\": \"29BDF297-EB43-403A-8719-A78DA11A2948\",                                     // Fisherman's Wharf\n        \"b3-3\": \"85CE77BF-3413-4A7B-9B0F-732E96229A73\"                                     // Embarcadero, Market Street\n    ]\n\n    // Extra info to be merged for a given ID, as of right now only one known video\n    let mergeInfo = [\n        \"2F11E857-4F77-4476-8033-4A1E4610AFCC\":\n            [\"url-1080-SDR\": \"https://sylvan.apple.com/Aerials/2x/Videos/DB_D011_C009_2K_SDR_HEVC.mov\",\n             \"url-1080-HDR\": \"https://sylvan.apple.com/Aerials/2x/Videos/DB_D011_C009_2K_HDR_HEVC.mov\",\n             \"url-4K-SDR\": \"https://sylvan.apple.com/Aerials/2x/Videos/DB_D011_C009_4K_SDR_HEVC.mov\",\n             \"url-4K-HDR\": \"https://sylvan.apple.com/Aerials/2x/Videos/DB_D011_C009_4K_HDR_HEVC.mov\" ]    // Dubai night 2\n    ]\n\n    // Extra POI\n    let mergePOI = [\n        \"b6-1\": \"C001_C005_\",    // China day 4\n        \"b2-1\": \"C004_C003_\",    // China day 5\n        \"b5-1\": \"C003_C003_\",    // China day 6\n        \"7D4710EB-5BA4-42E6-AA60-68D77F67D9B9\": \"GL_G010_C006_\",             // Greenland night 1\n        \"b7-1\": \"H007_C003\",                                                 // Hawaii day 1\n        \"b1-1\": \"H005_C012_\",                                                // Hawaii day 2\n        \"b2-2\": \"H010_C006_\",                                                // Hawaii day 3\n        \"b4-1\": \"H004_C007_\",                                                // Hawaii day 4\n        \"b6-2\": \"H012_C009_\",                                                // Hawaii night 1\n        \"b8-1\": \"H004_C009_\",                                                // Hawaii night 2\n        \"6E2FC8AC-832D-46CF-B306-BB2A05030C17\": \"LW_L001_C006_\",             // Liwa day 1 LW_L001_C006_0\n        \"b6-3\": \"L010_C006_\",                                                // London day 1\n        \"b5-2\": \"L007_C007_\",                                                // London day 2\n        \"b1-2\": \"L012_C002_\",                                                // London night 1\n        \"b3-1\": \"L004_C011_\",                                                // London night 2\n        \"A284F0BF-E690-4C13-92E2-4672D93E8DE5\": \"LA_A011_C003_\",             // Los Angeles night 3\n        \"b7-2\": \"N008_C009_\",                                                // New York day 1\n        \"b1-3\": \"N006_C003_\",                                                // New York day 2\n        \"b3-2\": \"N003_C006_\",                                                // New York day 3\n        \"b2-3\": \"N013_C004_\",                                                // New York night 1\n        \"b4-2\": \"N008_C003_\",                                                // New York night 2\n\n        \"b8-2\": \"A008_C007_\",                                                // San Francisco day 1\n        // \"b10-3\": ,                                               // San Francisco day 2\n        \"b9-3\": \"A006_C003_\",                                                // San Francisco day 3\n        // \"b8-3\":\"\",     San Francisco day 4 (no extra poi ?)\n        \"b3-3\": \"A012_C014_\",                                                // San Francisco day 5\n                                                                            //   maybe A013_C004 ?\n        \"b4-3\": \"A013_C005_\",                                                // San Francisco day 6\n        \"b6-4\": \"A004_C012_\",                                                // San Francisco night 1\n        \"b7-3\": \"A007_C017_\",                                                // San Francisco night 2\n        \"b5-3\": \"A015_C014_\",                                                // San Francisco night 3\n        \"b1-4\": \"A015_C018_\",                                                // San Francisco night 4\n        \"b2-4\": \"A018_C014_\"                                                 // San Francisco night 5\n    ]\n\n    // MARK: - Playlist generation\n    func generatePlaylist(isRestricted: Bool, restrictedTo: String) {\n        // Start fresh\n        playlist = [AerialVideo]()\n        playlistIsRestricted = isRestricted\n        playlistRestrictedTo = restrictedTo\n\n        // Start with a shuffled list, we may have synchronized seed shuffle\n        var shuffled: [AerialVideo]\n        /*if preferences.synchronizedMode {\n            if #available(OSX 10.11, *) {\n                let date = Date()\n                let calendar = NSCalendar.current\n                let minutes = calendar.component(.minute, from: date)\n                debugLog(\"seed : \\(minutes)\")\n\n                var generator = SeededGenerator(seed: UInt64(minutes))\n                shuffled = loadedManifest.shuffled(using: &generator)\n            } else {\n                // Fallback on earlier versions\n                shuffled = loadedManifest.shuffled()\n            }\n        } else {\n            shuffled = loadedManifest.shuffled()\n        }*/\n        // Somehow code above doesn't work anymore, force disabling it for everyone for now\n        shuffled = loadedManifest.shuffled()\n\n        for video in shuffled {\n            // We exclude videos not in rotation\n            /*let inRotation = preferences.videoIsInRotation(videoID: video.id)\n\n            if !inRotation {\n                continue\n            }*/\n\n            // Do we restrict video types by day/night ?\n            if isRestricted {\n                if video.timeOfDay != restrictedTo {\n                    continue\n                }\n            }\n\n            // Are we in full manual mode ?? This replace the old never stream setting\n            if !video.isAvailableOffline && !PrefsCache.enableManagement {\n                continue\n            }\n\n            // Is the video cached, and if not, are we full ?\n            if !video.isAvailableOffline && Cache.isFull() {\n                continue\n            }\n\n            // If the video isn't cached, can we network ?\n            if !video.isAvailableOffline && !Cache.canNetwork() {\n                continue\n            }\n\n            // All good ? Add to playlist\n            playlist.append(video)\n        }\n\n        // On regenerating a new playlist, we try to avoid repeating the last thing we played!\n        while playlist.count > 1 && lastPluckedFromPlaylist == playlist.first {\n            playlist.shuffle()\n        }\n    }\n\n    func randomVideo(excluding: [AerialVideo]) -> (AerialVideo?, Bool) {\n        var shouldLoop = false\n        let timeManagement = TimeManagement.sharedInstance\n        let (shouldRestrictByDayNight, restrictTo) = timeManagement.shouldRestrictPlaybackToDayNightVideo()\n\n        // We may need to regenerate a playlist!\n        if playlist.isEmpty || restrictTo != playlistRestrictedTo || shouldRestrictByDayNight != playlistIsRestricted {\n            generatePlaylist(isRestricted: shouldRestrictByDayNight, restrictedTo: restrictTo)\n            if playlist.count == 1 {\n                debugLog(\"playlist only has one element, looping!\")\n                shouldLoop = true\n            }\n        }\n\n        // If not pluck one from current playlist and return that\n        if !playlist.isEmpty {\n            lastPluckedFromPlaylist = playlist.removeFirst()\n            return (lastPluckedFromPlaylist, shouldLoop)\n        } else {\n            // If we don't have any playlist, something's got awfully wrong so deal with that!\n            return (findBestEffortVideo(), shouldLoop)\n        }\n    }\n\n    // Find a backup plan when conditions are not met\n    func findBestEffortVideo() -> AerialVideo? {\n        // So this is embarassing. This can happen if :\n        // - No video checked\n        // - No video for current conditions (only day video checked, and looking for night)\n        // - We don't want to stream but don't have any video\n        // - We may not have the manifests\n        // At this point we're doing a best effort :\n        // - Did we play something previously ? If so play that back (will loop)\n        // - return a random one from the manifest that is cached\n        // - return a random video that is not cached (slight betrayal of the Never stream videos)\n\n        warnLog(\"Empty playlist, not good !\")\n\n        if lastPluckedFromPlaylist != nil {\n            warnLog(\"Repeating last played video, after condition change not met !\")\n            return lastPluckedFromPlaylist!\n        } else {\n            // Start with a shuffled list\n            let shuffled = loadedManifest.shuffled()\n\n            if shuffled.isEmpty {\n                // This is super bad, no manifest at all\n                errorLog(\"No manifest, nothing to play !\")\n                return nil\n            }\n\n            /*for video in shuffled {\n                // We exclude videos not in rotation\n                let inRotation = preferences.videoIsInRotation(videoID: video.id)\n\n                // If we find anything cached and in rotation, we send that back\n                if video.isAvailableOffline && inRotation {\n                    warnLog(\"returning random cached in rotation video after condition change not met !\")\n                    return video\n                }\n            }*/\n            // Nothing ? Sorry but you'll get a non cached file\n            warnLog(\"returning random video after condition change not met !\")\n            return shuffled.first!\n        }\n    }\n\n    // MARK: - Lifecycle\n\n    init() {\n\n        debugLog(\"Manifest init\")\n        // 2.0 remove everything here\n/*\n        // tmp\n        loadCustomVideos()\n        // We try to load our video manifests in 3 steps :\n        // - reload from local variables (unused for now, maybe with previews+screensaver\n        // in some weird edge case on some systems)\n        // - reprocess the saved files in cache directory (full offline mode)\n        // - download the manifests from servers\n        //\n        // Starting with 1.4.6, we also may now periodically recheck for changed files!\n\n        debugLog(\"isManifestCached 10 \\(isManifestCached(manifest: .tvOS10))\")\n        debugLog(\"isManifestCached 11 \\(isManifestCached(manifest: .tvOS11))\")\n        debugLog(\"isManifestCached 12 \\(isManifestCached(manifest: .tvOS12))\")\n        debugLog(\"isManifestCached 13 \\(isManifestCached(manifest: .tvOS13))\")\n\n        checkIfShouldRedownloadFiles()\n\n        if areManifestsFilesLoaded() {\n            debugLog(\"Files were already loaded in memory\")\n            loadManifestsFromLoadedFiles()\n        } else {\n            debugLog(\"Files were not already loaded in memory\")\n            // Manifests are not in our preferences plist, are they cached on disk ?\n            if areManifestsCached() {\n                debugLog(\"Manifests are cached on disk, loading\")\n                loadCachedManifests()\n            } else {\n                // Ok then, we fetch them...\n                debugLog(\"Fetching missing manifests online\")\n                let dateFormatter = DateFormatter()\n                let current = Date()\n                dateFormatter.dateFormat = \"yyyy-MM-dd\"\n                preferences.lastVideoCheck = dateFormatter.string(from: current)\n\n                let downloadManager = DownloadManager()\n\n                var urls: [URL] = []\n\n                // For tvOS12-13, json is now in a tar file\n                if !isManifestCached(manifest: .tvOS13) || !isManifestCached(manifest: .tvOS13Strings) {\n                    urls.append(URL(string: \"https://sylvan.apple.com/Aerials/resources-13.tar\")!)\n                }\n\n                if !isManifestCached(manifest: .tvOS12) {\n                    urls.append(URL(string: \"https://sylvan.apple.com/Aerials/resources.tar\")!)\n                }\n\n                if !isManifestCached(manifest: .tvOS11) {\n                    urls.append(URL(string: \"https://sylvan.apple.com/Aerials/2x/entries.json\")!)\n                }\n\n                if !isManifestCached(manifest: .tvOS10) {\n                    urls.append(URL(string: \"http://a1.phobos.apple.com/us/r1000/000/Features/atv/AutumnResources/videos/entries.json\")!)\n                }\n\n                let completion = BlockOperation {\n                    debugLog(\"Fetching manifests all done\")\n                    // We can now load from the newly cached files\n                    self.loadCachedManifests()\n\n                }\n\n                for url in urls {\n                    let operation = downloadManager.queueDownload(url, folder: \"\")\n                    completion.addDependency(operation)\n                }\n\n                OperationQueue.main.addOperation(completion)\n            }\n        }*/\n    }\n\n    // MARK: - This will refetch the manifests online\n    func reloadFiles() {\n        moveOldManifests()\n\n        // Ok then, we fetch them...\n        debugLog(\"Fetching missing manifests online\")\n        let dateFormatter = DateFormatter()\n        let current = Date()\n        dateFormatter.dateFormat = \"yyyy-MM-dd\"\n        PrefsVideos.lastVideoCheck = dateFormatter.string(from: current)\n\n        let downloadManager = DownloadManager()\n\n        var urls: [URL] = []\n\n        // For tvOS12, json is now in a tar file\n        if !isManifestCached(manifest: .tvOS13) {\n            urls.append(URL(string: \"https://sylvan.apple.com/Aerials/resources-13.tar\")!)\n        }\n\n        if !isManifestCached(manifest: .tvOS12) {\n            urls.append(URL(string: \"https://sylvan.apple.com/Aerials/resources.tar\")!)\n        }\n\n        if !isManifestCached(manifest: .tvOS11) {\n            urls.append(URL(string: \"https://sylvan.apple.com/Aerials/2x/entries.json\")!)\n        }\n\n        if !isManifestCached(manifest: .tvOS10) {\n            urls.append(URL(string: \"http://a1.phobos.apple.com/us/r1000/000/Features/atv/AutumnResources/videos/entries.json\")!)\n        }\n\n        // Setup and start async fetching\n        let completion = BlockOperation {\n            debugLog(\"Fetching manifests all done\")\n            // We can now load from the newly cached files\n            self.loadCachedManifests()\n        }\n        for url in urls {\n            let operation = downloadManager.queueDownload(url, folder: \"\")\n            completion.addDependency(operation)\n        }\n        OperationQueue.main.addOperation(completion)\n    }\n\n    func addCallback(_ callback:@escaping ManifestLoadCallback) {\n        if !loadedManifest.isEmpty {\n            callback(loadedManifest)\n        } else {\n            callbacks.append(callback)\n        }\n    }\n\n    // MARK: - Custom videos\n    func loadCustomVideos() {\n        do {\n            if let cacheDirectory = VideoCache.appSupportDirectory {\n                // customvideos.json\n                var cacheFileUrl = URL(fileURLWithPath: cacheDirectory as String)\n                cacheFileUrl.appendPathComponent(\"customvideos.json\")\n                if FileManager.default.fileExists(atPath: cacheFileUrl.path) {\n                    debugLog(\"loading custom file : \\(cacheFileUrl)\")\n                    let ndata = try Data(contentsOf: cacheFileUrl)\n                    customVideoFolders = try CustomVideoFolders(data: ndata)\n                } else {\n                    debugLog(\"No customvideos.json at : \\(cacheFileUrl.path)\")\n                }\n            }\n        } catch {\n            debugLog(\"Error loading customvideos.json : \\(error)\")\n        }\n    }\n\n    func saveCustomVideos() {\n        if let cvf = customVideoFolders, let cacheDirectory = VideoCache.appSupportDirectory {\n            var cacheFileUrl = URL(fileURLWithPath: cacheDirectory as String)\n            cacheFileUrl.appendPathComponent(\"customvideos.json\")\n\n            do {\n                if let encodedData = try? cvf.jsonData() {\n                    try encodedData.write(to: cacheFileUrl)\n                    debugLog(\"customvideos.json saved successfully!\")\n                    loadedManifest.removeAll()  // we remove our previously loaded manifest, it's invalid\n                }\n            } catch let error as NSError {\n                errorLog(\"customvideos.json could not be saved: \\(error.localizedDescription)\")\n            }\n        }\n    }\n\n    // This is where we merge with the processed list\n    func mergeCustomVideos() {\n        /*\n        if let cvf = customVideoFolders {\n            for folder in cvf.folders {\n                for asset in folder.assets {\n                    let avResolution = getResolution(asset: AVAsset(url: URL(fileURLWithPath: asset.url)))\n                    var url1080p = \"\"\n                    var url4K = \"\"\n\n                    if avResolution.height > 1080 {\n                        url4K = URL(fileURLWithPath: asset.url).absoluteString\n                    } else {\n                        url1080p = URL(fileURLWithPath: asset.url).absoluteString\n                    }\n\n                    let urls: [VideoFormat: String] = [.v1080pH264: url1080p,\n                                                       .v1080pHEVC: url1080p,\n                                                       .v1080pHDR: url1080p,\n                                                       .v4KHEVC: url4K,\n                                                       .v4KHDR: url4K, ]\n                    let video = AerialVideo(id: asset.id,\n                                                name: folder.label,\n                                                secondaryName: asset.accessibilityLabel,\n                                                type: \"video\",\n                                                timeOfDay: asset.time,\n                                                scene: \"landscape\",\n                                                urls: urls,\n                                                source: nil,\n                                                poi: [:],\n                                                communityPoi: asset.pointsOfInterest)\n                    processedVideos.append(video)\n                }\n            }\n        }\n         */\n    }\n\n    func getResolution(asset: AVAsset) -> CGSize {\n        guard let track = asset.tracks(withMediaType: AVMediaType.video).first else { return CGSize.zero }\n        let size = track.naturalSize.applying(track.preferredTransform)\n        return CGSize(width: abs(size.width), height: abs(size.height))\n    }\n\n    // MARK: - Periodically check for new videos\n    func checkIfShouldRedownloadFiles() {\n        let dateFormatter = DateFormatter()\n        dateFormatter.dateFormat = \"yyyy-MM-dd\"\n        dateFormatter.locale = Locale.init(identifier: \"en_GB\")\n        let dateObj = dateFormatter.date(from: PrefsVideos.lastVideoCheck)\n\n        debugLog(PrefsVideos.lastVideoCheck)\n\n        var dayCheck: Int\n\n        switch PrefsVideos.refreshPeriodicity {\n        case .weekly:\n            dayCheck = 7\n        case .monthly:\n            dayCheck = 30\n        case .never:\n            dayCheck = 9999\n        }\n\n        let cacheDirectory = VideoCache.appSupportDirectory!\n        var cacheResourcesString = cacheDirectory\n        cacheResourcesString.append(contentsOf: \"/backups\")\n        let cacheUrl = URL(fileURLWithPath: cacheResourcesString)\n\n        if #available(OSX 10.11, *) {\n            if !cacheUrl.hasDirectoryPath {\n                // If there's no backup directory, we force the first check\n                moveOldManifests()\n                return\n            }\n        } else {\n            // Fallback on earlier versions\n        }\n\n        //debugLog(\"Interval : \\(String(describing: dateObj?.timeIntervalSinceNow))\")\n        if Int((dateObj?.timeIntervalSinceNow)!) < -dayCheck * 86400 {\n            // We need to redownload then\n            debugLog(\"Checking for new videos\")\n            moveOldManifests()\n        } else {\n            debugLog(\"No need to check for new videos\")\n        }\n    }\n\n    // We only backup the current tvos and TVStringsBundle (tvOS13)\n    // Previous versions don't change\n    func moveOldManifests() {\n        debugLog(\"move\")\n        let cacheDirectory = VideoCache.appSupportDirectory!\n        var cacheResourcesString = cacheDirectory\n\n        // Generate the backup path\n        let dateFormatter = DateFormatter()\n        let current = Date()\n        dateFormatter.dateFormat = \"yyyy-MM-dd\"\n        let today = dateFormatter.string(from: current)\n        cacheResourcesString.append(contentsOf: \"/backups/\"+today)\n\n        // The previous files we want to move\n        let previous = URL(fileURLWithPath: cacheDirectory.appending(\"/tvos13.json\"))\n        let previousBnd = URL(fileURLWithPath: cacheDirectory.appending(\"/TVIdleScreenStrings13.bundle\"))\n\n        if FileManager.default.fileExists(atPath: cacheDirectory.appending(\"/tvos13.json\")) || FileManager.default.fileExists(atPath: cacheDirectory.appending(\"/TVIdleScreenStrings13.bundle\")) {\n            let new = URL(fileURLWithPath: cacheResourcesString.appending(\"/tvos13.json\"))\n            let newBnd = URL(fileURLWithPath: cacheResourcesString.appending(\"/TVIdleScreenStrings13.bundle\"))\n\n            let cacheUrl = URL(fileURLWithPath: cacheResourcesString)\n            if #available(OSX 10.11, *) {\n                if !cacheUrl.hasDirectoryPath {\n                    do {\n                        debugLog(\"creating dir \\(cacheResourcesString)\")\n                        try FileManager.default.createDirectory(atPath: cacheResourcesString, withIntermediateDirectories: true, attributes: nil)\n\n                        debugLog(\"moving tvos13.json and TVIdleScreenStrings13.bundle\")\n                        try FileManager.default.moveItem(at: previous, to: new)\n                        try FileManager.default.moveItem(at: previousBnd, to: newBnd)\n                    } catch {\n                        errorLog(\"\\(error.localizedDescription)\")\n                    }\n                }\n            }\n        }\n    }\n\n    // MARK: - Manifests\n\n    // Check if the Manifests have been loaded in this class already\n    func areManifestsFilesLoaded() -> Bool {\n        if manifestTvOS13 != nil && manifestTvOS12 != nil && manifestTvOS11 != nil && manifestTvOS10 != nil {\n            debugLog(\"Manifests files were loaded in class\")\n            return true\n        } else {\n            debugLog(\"Manifests files were not loaded in class\")\n            return false\n        }\n    }\n\n    // Check if the Manifests are saved in our cache directory\n    func areManifestsCached() -> Bool {\n        return isManifestCached(manifest: .tvOS10) && isManifestCached(manifest: .tvOS11) && isManifestCached(manifest: .tvOS12) && isManifestCached(manifest: .tvOS13) && isManifestCached(manifest: .tvOS13Strings)\n    }\n\n    // Check if a Manifest is saved in our cache directory\n    func isManifestCached(manifest: Manifests) -> Bool {\n        if let cacheDirectory = VideoCache.appSupportDirectory {\n            let fileManager = FileManager.default\n\n            var cacheResourcesString = cacheDirectory\n            cacheResourcesString.append(contentsOf: \"/\" + manifest.rawValue)\n\n            if !fileManager.fileExists(atPath: cacheResourcesString) {\n                return false\n            }\n        } else {\n            return false\n        }\n\n        return true\n    }\n\n    // Load the JSON Data cached on disk\n    func loadCachedManifests() {\n        if let cacheDirectory = VideoCache.appSupportDirectory {\n            // tvOS13\n            var cacheFileUrl = URL(fileURLWithPath: cacheDirectory as String)\n            cacheFileUrl.appendPathComponent(\"tvos13.json\")\n            do {\n                let ndata = try Data(contentsOf: cacheFileUrl)\n                manifestTvOS13 = ndata\n            } catch {\n                errorLog(\"Can't load tvos13.json from cached directory\")\n            }\n\n            // tvOS12\n            cacheFileUrl = URL(fileURLWithPath: cacheDirectory as String)\n            cacheFileUrl.appendPathComponent(\"tvos12.json\")\n            do {\n                let ndata = try Data(contentsOf: cacheFileUrl)\n                manifestTvOS12 = ndata\n            } catch {\n                errorLog(\"Can't load tvos12.json from cached directory\")\n            }\n\n            // tvOS11\n            cacheFileUrl = URL(fileURLWithPath: cacheDirectory as String)\n            cacheFileUrl.appendPathComponent(\"tvos11.json\")\n            do {\n                let ndata = try Data(contentsOf: cacheFileUrl)\n                manifestTvOS11 = ndata\n            } catch {\n                errorLog(\"Can't load tvos11.json from cached directory\")\n            }\n\n            // tvOS10\n            cacheFileUrl = URL(fileURLWithPath: cacheDirectory as String)\n            cacheFileUrl.appendPathComponent(\"tvos10.json\")\n            do {\n                let ndata = try Data(contentsOf: cacheFileUrl)\n                manifestTvOS10 = ndata\n            } catch {\n                errorLog(\"Can't load tvos10.json from cached directory\")\n            }\n\n            if manifestTvOS10 != nil || manifestTvOS11 != nil || manifestTvOS12 != nil || manifestTvOS13 != nil {\n                loadManifestsFromLoadedFiles()\n            } else {\n                // No internet, no anything, nothing to do\n                errorLog(\"No video to load, no internet connexion ?\")\n            }\n        }\n    }\n\n    // Load Manifests from the saved preferences\n    func loadManifestsFromLoadedFiles() {\n        // Reset our array\n        processedVideos = []\n\n        if manifestTvOS13 != nil {\n            // We start with the more recent one, it has more information (poi, etc)\n            readJSONFromData(manifestTvOS13!, manifest: .tvOS13)\n        } else {\n            warnLog(\"tvOS13 manifest is absent\")\n        }\n\n        if manifestTvOS12 != nil {\n            // We start with the more recent one, it has more information (poi, etc)\n            readJSONFromData(manifestTvOS12!, manifest: .tvOS12)\n\n            // We also need to add the missing videos\n            let bundlePath = Bundle(for: ManifestLoader.self).path(forResource: \"missingvideos\", ofType: \"json\")!\n            do {\n                let data = try Data(contentsOf: URL(fileURLWithPath: bundlePath), options: .mappedIfSafe)\n                readJSONFromData(data, manifest: .tvOS12)\n            } catch {\n                errorLog(\"missingvideos.json was not found in the bundle\")\n            }\n        } else {\n            warnLog(\"tvOS12 manifest is absent\")\n        }\n\n        if manifestTvOS11 != nil {\n            // This one has a couple videos not in the tvOS12 JSON. No H264 for these !\n            readJSONFromData(manifestTvOS11!, manifest: .tvOS11)\n        } else {\n            warnLog(\"tvOS11 manifest is absent\")\n        }\n\n        if manifestTvOS10 != nil {\n            // The original manifest is in another format\n            readOldJSONFromData(manifestTvOS10!, manifest: .tvOS10)\n        } else {\n            warnLog(\"tvOS10 manifest is absent\")\n        }\n\n        if customVideoFolders != nil {\n            mergeCustomVideos()\n        }\n\n        // We sort videos by secondary names, so they can display sorted in our view later\n        processedVideos = processedVideos.sorted { $0.secondaryName < $1.secondaryName }\n\n        self.loadedManifest = processedVideos\n\n        debugLog(\"Total videos processed : \\(processedVideos.count) callbacks : \\(callbacks.count)\")\n        // callbacks\n        for callback in self.callbacks {\n            callback(self.loadedManifest)\n        }\n        self.callbacks.removeAll()\n    }\n\n    // MARK: - JSON\n    func readJSONFromData(_ data: Data, manifest: Manifests) {\n        /*\n        do {\n            let poiStringProvider = PoiStringProvider.sharedInstance\n\n            let options = JSONSerialization.ReadingOptions.allowFragments\n            let batches = try JSONSerialization.jsonObject(with: data, options: options)\n\n            guard let batch = batches as? NSDictionary else {\n                errorLog(\"Encountered unexpected content type for batch, please report !\")\n                return\n            }\n\n            let assets = batch[\"assets\"] as! [NSDictionary]\n\n            for item in assets {\n                let id = item[\"id\"] as! String\n                let url1080pH264 = item[\"url-1080-H264\"] as? String\n                let url1080pHEVC = item[\"url-1080-SDR\"] as? String\n                let url1080pHDR = item[\"url-1080-HDR\"] as? String\n                let url4KHEVC = item[\"url-4K-SDR\"] as? String\n                let url4KHDR = item[\"url-4K-HDR\"] as? String\n                let name = item[\"accessibilityLabel\"] as! String\n\n                let urls: [VideoFormat: String] = [.v1080pH264: url1080pH264 ?? \"\",\n                                                   .v1080pHEVC: url1080pHEVC ?? \"\",\n                                                   .v1080pHDR: url1080pHDR ?? \"\",\n                                                   .v4KHEVC: url4KHEVC ?? \"\",\n                                                   .v4KHDR: url4KHDR ?? \"\", ]\n                var secondaryName = \"\"\n                // We may have a secondary name\n                if let mergename = poiStringProvider.getCommunityName(id: id) {\n                    secondaryName = mergename\n                }\n\n                let timeOfDay = \"day\"   // TODO, this is hardcoded as it's no longer available in the modern JSONs\n                let type = \"video\"\n                var poi: [String: String]?\n                if let mergeId = mergePOI[id] {\n                    poi = poiStringProvider.fetchExtraPoiForId(id: mergeId)\n                } else {\n                    poi = item[\"pointsOfInterest\"] as? [String: String]\n                }\n\n                let communityPoi = poiStringProvider.getCommunityPoi(id: id)\n\n                let (isDupe, foundDupe) = findDuplicate(id: id, url1080pH264: url1080pH264 ?? \"\")\n                if isDupe {\n                    //foundDupe!.sources.append(manifest)\n                } else {\n                    let video = AerialVideo(id: id,             // Must have\n                        name: name,                             // Must have\n                        secondaryName: secondaryName,           // Optional\n                        type: type,                             // Not sure the point of this one ?\n                        timeOfDay: timeOfDay,\n                        scene: \"landscape\",\n                        urls: urls,\n                        source: nil,\n                        poi: poi ?? [:],\n                        communityPoi: communityPoi)\n\n                    processedVideos.append(video)\n                }\n            }\n        } catch {\n            errorLog(\"Error retrieving content listing (new)\")\n            return\n        }*/\n    }\n\n    func readOldJSONFromData(_ data: Data, manifest: Manifests) {\n        /*\n        do {\n            let poiStringProvider = PoiStringProvider.sharedInstance\n\n            let options = JSONSerialization.ReadingOptions.allowFragments\n            let batches = try JSONSerialization.jsonObject(with: data,\n                                                           options: options) as! [NSDictionary]\n\n            for batch: NSDictionary in batches {\n                let assets = batch[\"assets\"] as! [NSDictionary]\n\n                for item in assets {\n                    let url = item[\"url\"] as! String\n                    let name = item[\"accessibilityLabel\"] as! String\n                    let timeOfDay = item[\"timeOfDay\"] as! String\n                    let id = item[\"id\"] as! String\n                    let type = item[\"type\"] as! String\n\n                    if type != \"video\" {\n                        continue\n                    }\n\n                    // We may have a secondary name\n                    var secondaryName = \"\"\n                    if let mergename = poiStringProvider.getCommunityName(id: id) {\n                        secondaryName = mergename\n                    }\n\n                    // We may have POIs to merge\n                    var poi: [String: String]?\n                    if let mergeId = mergePOI[id] {\n                        let poiStringProvider = PoiStringProvider.sharedInstance\n                        poi = poiStringProvider.fetchExtraPoiForId(id: mergeId)\n                    }\n\n                    let communityPoi = poiStringProvider.getCommunityPoi(id: id)\n\n                    // We may have dupes...\n                    let (isDupe, foundDupe) = findDuplicate(id: id, url1080pH264: url)\n                    if isDupe {\n                        if foundDupe != nil {\n                            //foundDupe!.sources.append(manifest)\n\n                            if foundDupe?.urls[.v1080pH264] == \"\" {\n                                foundDupe?.urls[.v1080pH264] = url\n                            }\n                        }\n                    } else {\n                        var url1080pHEVC = \"\"\n                        var url1080pHDR = \"\"\n                        var url4KHEVC = \"\"\n                        var url4KHDR = \"\"\n\n                        // Check if we have some HEVC urls to merge\n                        if let val = mergeInfo[id] {\n                            url1080pHEVC = val[\"url-1080-SDR\"]!\n                            url1080pHDR = val[\"url-1080-HDR\"]!\n                            url4KHEVC = val[\"url-4K-SDR\"]!\n                            url4KHDR = val[\"url-4K-HDR\"]!\n                        }\n\n                        let urls: [VideoFormat: String] = [.v1080pH264: url,\n                                                           .v1080pHEVC: url1080pHEVC,\n                                                           .v1080pHDR: url1080pHDR,\n                                                           .v4KHEVC: url4KHEVC,\n                                                           .v4KHDR: url4KHDR, ]\n\n                        // Now we can finally add...\n                        let video = AerialVideo(id: id,             // Must have\n                            name: name,         // Must have\n                            secondaryName: secondaryName,\n                            type: type,         // Not sure the point of this one ?\n                            timeOfDay: timeOfDay,\n                            scene: \"landscape\",\n                            urls: urls,\n                            source: Source(),\n                            poi: poi ?? [:],\n                            communityPoi: communityPoi)\n\n                        processedVideos.append(video)\n                    }\n                }\n            }\n        } catch {\n            errorLog(\"Error retrieving content listing (old)\")\n            return\n        }*/\n    }\n\n    // Look for a previously processed similar video\n    //\n    // tvOS11 and 12 JSON are using the same ID (and tvOS12 JSON always has better data,\n    // so no need for a fancy merge)\n    //\n    // tvOS10 however JSON DOES NOT use the same ID, so we need to dupecheck on the h264\n    // (only available format there) filename (they actually have different URLs !)\n    func findDuplicate(id: String, url1080pH264: String) -> (Bool, AerialVideo?) {\n        // We blacklist some duplicates\n        if url1080pH264 != \"\" {\n            if blacklist.contains((URL(string: url1080pH264)?.lastPathComponent)!) {\n                return (true, nil)\n            }\n        }\n\n        // We also have a Dictionary of duplicates that need source merging\n        for (pid, replace) in dupePairs where id == pid {\n            for vid in processedVideos where vid.id == replace {\n                // Found dupe pair\n                return (true, vid)\n            }\n        }\n\n        for video in processedVideos {\n            if id == video.id {\n                return (true, video)\n            } else if url1080pH264 != \"\" && video.urls[.v1080pH264] != \"\" {\n                if URL(string: url1080pH264)?.lastPathComponent == URL(string: video.urls[.v1080pH264]!)?.lastPathComponent {\n                    return (true, video)\n                }\n            }\n        }\n\n        return (false, nil)\n    }\n\n    // MARK: - Old video management\n    // Try to estimate how many old (unlinked) files we have\n    func getOldFilesEstimation() -> (String, Int) {\n        // loadedManifests contains the full deduplicated list of videos\n        debugLog(\"Looking for outdated files\")\n\n        if loadedManifest.isEmpty {\n            warnLog(\"We have no videos in the manifest\")\n            return (\"Can't estimate duplicates\", 0)\n        }\n        guard let cacheDirectory = VideoCache.appSupportDirectory else {\n            warnLog(\"No cache directory\")\n            return (\"Can't estimate duplicates\", 0)\n        }\n\n        var foundOldFiles = 0\n\n        let cacheDirectoryUrl = URL(fileURLWithPath: cacheDirectory as String)\n        let fileManager = FileManager.default\n        do {\n            let directoryContent = try fileManager.contentsOfDirectory(at: cacheDirectoryUrl, includingPropertiesForKeys: nil)\n            let videoFileURLs = directoryContent.filter { $0.pathExtension == \"mov\" }\n\n            // We check all formats we may have\n            for fileURL in videoFileURLs {\n                var found = false\n                for video in loadedManifest {\n                    for format in VideoFormat.allCases where video.urls[format] != \"\" {\n                        if fileURL.lastPathComponent == URL(string: video.urls[format]!)?.lastPathComponent {\n                            found = true\n                            break\n                        }\n                    }\n                }\n\n                if !found {\n                    debugLog(\"\\(fileURL.lastPathComponent) NOT FOUND in manifest\")\n                    foundOldFiles += 1\n                }\n            }\n        } catch {\n            errorLog(\"Error while enumerating files \\(cacheDirectoryUrl.path): \\(error.localizedDescription)\")\n        }\n\n        if foundOldFiles == 0 {\n            debugLog(\"No old files found\")\n            return (\"No old files found\", 0)\n        }\n        debugLog(\"\\(foundOldFiles) old files found\")\n        return (\"\\(foundOldFiles) old files found\", foundOldFiles)\n    }\n/*\n    func moveOldVideos() {\n        debugLog(\"move old videos\")\n        let cacheDirectory = VideoCache.appSupportDirectory!\n        var cacheResourcesString = cacheDirectory\n\n        let dateFormatter = DateFormatter()\n        let current = Date()\n        dateFormatter.dateFormat = \"yyyy-MM-dd\"\n        let today = dateFormatter.string(from: current)\n\n        cacheResourcesString.append(contentsOf: \"/oldvideos/\"+today)\n\n        let cacheUrl = URL(fileURLWithPath: cacheResourcesString)\n        if #available(OSX 10.11, *) {\n            if !cacheUrl.hasDirectoryPath {\n                do {\n                    try FileManager.default.createDirectory(atPath: cacheResourcesString, withIntermediateDirectories: true, attributes: nil)\n                    debugLog(\"creating dir \\(cacheResourcesString)\")\n                } catch {\n                    errorLog(\"\\(error.localizedDescription)\")\n                }\n            }\n        }\n\n        if loadedManifest.isEmpty {\n            warnLog(\"We have no videos in the manifest\")\n            return\n        }\n\n        let cacheDirectoryUrl = URL(fileURLWithPath: cacheDirectory as String)\n        let fileManager = FileManager.default\n        do {\n            let directoryContent = try fileManager.contentsOfDirectory(at: cacheDirectoryUrl, includingPropertiesForKeys: nil)\n            let videoFileURLs = directoryContent.filter { $0.pathExtension == \"mov\" }\n\n            // We check the 5 fields\n            for fileURL in videoFileURLs {\n                var found = false\n                for video in loadedManifest {\n                    for format in VideoFormat.allCases where video.urls[format] != \"\" {\n                        if fileURL.lastPathComponent == URL(string: video.urls[format]!)?.lastPathComponent {\n                            found = true\n                            break\n                        }\n                    }\n                }\n\n                if !found {\n                    do {\n                        debugLog(\"moving \\(fileURL.lastPathComponent)\")\n                        let new = URL(fileURLWithPath: cacheResourcesString.appending(\"/\\(fileURL.lastPathComponent)\"))\n                        try FileManager.default.moveItem(at: fileURL, to: new)\n                    } catch {\n                        errorLog(\"\\(error.localizedDescription)\")\n                    }\n                }\n            }\n        } catch {\n            errorLog(\"Error while enumerating files \\(cacheDirectoryUrl.path): \\(error.localizedDescription)\")\n        }\n    }\n\n    func trashOldVideos() {\n        debugLog(\"trash old videos\")\n        let cacheDirectory = VideoCache.appSupportDirectory!\n        var cacheResourcesString = cacheDirectory\n\n        let dateFormatter = DateFormatter()\n        let current = Date()\n        dateFormatter.dateFormat = \"yyyy-MM-dd\"\n        let today = dateFormatter.string(from: current)\n\n        cacheResourcesString.append(contentsOf: \"/oldvideos/\"+today)\n\n        let cacheUrl = URL(fileURLWithPath: cacheResourcesString)\n        if #available(OSX 10.11, *) {\n            if !cacheUrl.hasDirectoryPath {\n                do {\n                    try FileManager.default.createDirectory(atPath: cacheResourcesString, withIntermediateDirectories: true, attributes: nil)\n                    debugLog(\"creating dir \\(cacheResourcesString)\")\n                } catch {\n                    errorLog(\"\\(error.localizedDescription)\")\n                }\n            }\n        }\n\n        if loadedManifest.isEmpty {\n            warnLog(\"We have no videos in the manifest\")\n            return\n        }\n\n        let cacheDirectoryUrl = URL(fileURLWithPath: cacheDirectory as String)\n        let fileManager = FileManager.default\n        do {\n            let directoryContent = try fileManager.contentsOfDirectory(at: cacheDirectoryUrl, includingPropertiesForKeys: nil)\n            let videoFileURLs = directoryContent.filter { $0.pathExtension == \"mov\" }\n\n            // We check the 5 fields\n            for fileURL in videoFileURLs {\n                var found = false\n                for video in loadedManifest {\n                    for format in VideoFormat.allCases where video.urls[format] != \"\" {\n                        if fileURL.lastPathComponent == URL(string: video.urls[format]!)?.lastPathComponent {\n                            found = true\n                            break\n                        }\n                    }\n                }\n\n                if !found {\n                    debugLog(\"trashing \\(fileURL.lastPathComponent)\")\n\n                    NSWorkspace.shared.recycle([fileURL]) { trashedFiles, error in\n                        for file in [fileURL] where trashedFiles[file] == nil {\n                            errorLog(\"\\(file.relativePath) could not be moved to trash \\(error!.localizedDescription)\")\n                        }\n                    }\n                }\n            }\n        } catch {\n            errorLog(\"Error while enumerating files \\(cacheDirectoryUrl.path): \\(error.localizedDescription)\")\n        }\n    }*/\n\n} // swiftlint:disable:this file_length\n"
  },
  {
    "path": "Aerial/Source/Models/Music/Music.swift",
    "content": "//\n//  Music.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 29/06/2021.\n//  Copyright © 2021 Guillaume Louel. All rights reserved.\n//\n\nimport Foundation\nimport AppKit\n\ntypealias MusicCallback = (SongInfo) -> Void\n\nstruct SongInfo {\n    let name: String\n    let artist: String\n    let album: String\n    let artwork: NSImage?\n}\n\n// swiftlint:disable:next type_body_length\nclass Music {\n    static let instance: Music = Music()\n    var callbacks = [MusicCallback]()\n    var wasSetup = false\n\n    // This is called once at init to set our observer\n    func setup() {\n        if !wasSetup {\n            debugLog(\"🎧 registering private callback\")\n\n            // Load framework\n            let bundle = CFBundleCreate(kCFAllocatorDefault, NSURL(fileURLWithPath: \"/System/Library/PrivateFrameworks/MediaRemote.framework\"))\n            \n            // Get a Swift function for MRMediaRemoteRegisterForNowPlayingNotifications\n            guard let MRMediaRemoteRegisterForNowPlayingNotificationsPointer = CFBundleGetFunctionPointerForName(bundle, \"MRMediaRemoteRegisterForNowPlayingNotifications\" as CFString) else { return }\n            typealias MRMediaRemoteRegisterForNowPlayingNotificationsFunction = @convention(c) (DispatchQueue) -> Void\n            let MRMediaRemoteRegisterForNowPlayingNotifications = unsafeBitCast(MRMediaRemoteRegisterForNowPlayingNotificationsPointer, to: MRMediaRemoteRegisterForNowPlayingNotificationsFunction.self)\n            \n            // Call the register function\n            MRMediaRemoteRegisterForNowPlayingNotifications(DispatchQueue.main)\n            \n            DispatchQueue.main.async {\n                // Register App state change callback\n                NotificationCenter.default.addObserver(self,\n                                                       selector: #selector(Music.mediaRemoteAppStateChange(_:)),\n                                                       name: NSNotification.Name(\"kMRMediaRemoteNowPlayingApplicationIsPlayingDidChangeNotification\"), object: nil)\n                \n                // Register playback info change callback\n                NotificationCenter.default.addObserver(self,\n                                                       selector: #selector(Music.mediaRemoteCallback(_:)),\n                                                       name: NSNotification.Name(\"kMRMediaRemoteNowPlayingInfoDidChangeNotification\"), object: nil)\n            }\n\n            wasSetup = true\n        }\n    }\n\n    // Callback to get paused status from some apps that may not update info pause on change\n    @objc func mediaRemoteAppStateChange(_ aNotification: Notification) {\n        debugLog(\"🎧 app state change\")\n        \n        if let userInfo = aNotification.userInfo {\n            if let rate = userInfo[\"kMRMediaRemoteNowPlayingApplicationIsPlayingUserInfoKey\"] as? Double {\n                \n                if rate == 0 {\n                    debugLog(\"🎧 playback is paused, clearing\")\n                    // Pause the thing\n                    for callback in self.callbacks {\n                        callback(SongInfo(name: \"\", artist: \"\", album: \"\", artwork: nil))\n                    }\n                }\n            }\n        }\n    }\n    \n    // General info change callback\n    @objc func mediaRemoteCallback(_ aNotification: Notification?) {\n        var album = \"\"\n        var name = \"\"\n        var artist = \"\"\n        var artwork: NSImage?\n        \n        debugLog(\"🎧 media remote callback\")\n        // Load framework\n        let bundle = CFBundleCreate(kCFAllocatorDefault, NSURL(fileURLWithPath: \"/System/Library/PrivateFrameworks/MediaRemote.framework\"))\n\n        // Get a Swift function for MRMediaRemoteGetNowPlayingInfo\n        guard let MRMediaRemoteGetNowPlayingInfoPointer = CFBundleGetFunctionPointerForName(bundle, \"MRMediaRemoteGetNowPlayingInfo\" as CFString) else { return }\n        typealias MRMediaRemoteGetNowPlayingInfoFunction = @convention(c) (DispatchQueue, @escaping ([String: Any]) -> Void) -> Void\n        let MRMediaRemoteGetNowPlayingInfo = unsafeBitCast(MRMediaRemoteGetNowPlayingInfoPointer, to: MRMediaRemoteGetNowPlayingInfoFunction.self)\n        \n        // Get song info\n        MRMediaRemoteGetNowPlayingInfo(DispatchQueue.main, { (information) in\n            debugLog(\"🎧 audio info\")\n\n            \n            if let info = information[\"kMRMediaRemoteNowPlayingInfoPlaybackRate\"] as? Double {\n                if (info != 0.0) {\n                    // Player is running\n                    if let info = information[\"kMRMediaRemoteNowPlayingInfoArtist\"] as? String {\n                        artist = info\n                    }\n                    if let info = information[\"kMRMediaRemoteNowPlayingInfoTitle\"] as? String {\n                        name = info\n                    }\n                    if let info = information[\"kMRMediaRemoteNowPlayingInfoAlbum\"] as? String {\n                        album = info\n                    }\n\n\n                    // try to grab image from the keys\n                    if information.keys.contains(\"kMRMediaRemoteNowPlayingInfoArtworkData\") {\n                        if let _artwork = NSImage(data: information[\"kMRMediaRemoteNowPlayingInfoArtworkData\"] as! Data) {\n                            artwork = _artwork\n                        }\n                    }\n                    \n                    debugLog(\"🎧 \" + artist + \" - \" + name + \" (\" + album + \")\" + ((artwork != nil) ? \" with artwork \" : \" without artwork\"))\n                } else {\n                    debugLog(\"🎧 Player is paused\")\n                }\n            }\n            \n            // Let everyone who wants to know that we have a new song playing !\n            for callback in self.callbacks {\n                callback(SongInfo(name: name, artist: artist, album: album, artwork: artwork))\n            }\n        })\n    }\n    \n    // MARK: - Callbacks\n    func addCallback(_ callback:@escaping MusicCallback) {\n        debugLog(\"🎧 Adding music callback\")\n        callbacks.append(callback)\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Models/PlaybackSpeed.swift",
    "content": "//\n//  PlaybackSpeed.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 08/07/2021.\n//  Copyright © 2021 Guillaume Louel. All rights reserved.\n//\n\nimport Foundation\n\nstruct PlaybackSpeed {\n    static func forVideo(_ id: String) -> Float {\n        if let value = PrefsVideos.playbackSpeed[id] {\n            return value\n        } else {\n            return 1\n        }\n    }\n\n    static func update(video: String, value: Float) {\n        // Just in case...\n        if value == 0 {\n            PrefsVideos.playbackSpeed[video] = 0.01\n        } else {\n            PrefsVideos.playbackSpeed[video] = value\n        }\n    }\n\n    static func reset(video: String) {\n        PrefsVideos.playbackSpeed[video] = 1\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Models/Prefs/PrefsAdvanced.swift",
    "content": "//\n//  PrefsAdvanced.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 23/04/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Foundation\n\nstruct PrefsAdvanced {\n    // Display margins\n    @SimpleStorage(key: \"muteSound\", defaultValue: true)\n    static var muteSound: Bool\n\n    @SimpleStorage(key: \"muteGlobalSound\", defaultValue: false)\n    static var muteGlobalSound: Bool\n    \n    @SimpleStorage(key: \"autoPlayPreviews\", defaultValue: true)\n    static var autoPlayPreviews: Bool\n\n    @SimpleStorage(key: \"firstTimeSetup\", defaultValue: false)\n    static var firstTimeSetup: Bool\n\n    @SimpleStorage(key: \"favorOrientation\", defaultValue: true)\n    static var favorOrientation: Bool\n    \n    // Invert colors\n    @SimpleStorage(key: \"invertColors\", defaultValue: false)\n    static var invertColors: Bool\n    \n    // Debug mode\n    @SimpleStorage(key: \"debugMode\", defaultValue: false)\n    static var debugMode: Bool\n\n    // OVerride Language\n    @SimpleStorage(key: \"ciOverrideLanguage\", defaultValue: \"\")\n    static var ciOverrideLanguage: String\n\n    @SimpleStorage(key: \"newDisplayDict\", defaultValue: [String: Bool]())\n    static var newDisplayDict: [String: Bool]\n    \n    \n}\n"
  },
  {
    "path": "Aerial/Source/Models/Prefs/PrefsCache.swift",
    "content": "//\n//  PrefsCache.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 03/06/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Foundation\n\nenum CachePeriodicity: Int, Codable {\n    case daily, weekly, monthly, never\n}\n\nstruct PrefsCache {\n    @SimpleStorage(key: \"enableManagement\", defaultValue: true)\n    static var enableManagement: Bool\n\n    // Cache limit (in GiB)\n    @SimpleStorage(key: \"cacheLimit\", defaultValue: 5)\n    static var cacheLimit: Double\n\n    // How often should cache gets refreshed\n    @SimpleStorage(key: \"intCachePeriodicity\", defaultValue: CachePeriodicity.never.rawValue)\n    static var intCachePeriodicity: Int\n\n    // We wrap in a separate value, as we can't store an enum as a Codable in\n    // macOS < 10.15\n    static var cachePeriodicity: CachePeriodicity {\n        get {\n            return CachePeriodicity(rawValue: intCachePeriodicity)!\n        }\n        set(value) {\n            intCachePeriodicity = value.rawValue\n        }\n    }\n\n    // Do we restrict network traffic on Wi-Fi\n    @SimpleStorage(key: \"restrictOnWiFi\", defaultValue: false)\n    static var restrictOnWiFi: Bool\n\n    // List of allowed networks (using SSID)\n    @SimpleStorage(key: \"allowedNetworks\", defaultValue: [])\n    static var allowedNetworks: [String]\n\n    // Should we show the download indicator or not\n    @SimpleStorage(key: \"showBackgroundDownloads\", defaultValue: false)\n    static var showBackgroundDownloads: Bool\n\n    // Should we override the cache\n    @SimpleStorage(key: \"overrideCache\", defaultValue: false)\n    static var overrideCache: Bool\n\n    // App-scoped bookmark to cache, in NSData form\n    @SimpleStorage(key: \"cacheBookmarkData\", defaultValue: nil)\n    static var cacheBookmarkData: Data?\n\n    // The raw path in string form\n    @SimpleStorage(key: \"cachePath\", defaultValue: nil)\n    static var cachePath: String?\n    \n    // App-scoped bookmark to cache, in NSData form\n    @SimpleStorage(key: \"supportBookmarkData\", defaultValue: nil)\n    static var supportBookmarkData: Data?\n\n    // The raw path in string form\n    @SimpleStorage(key: \"supportPath\", defaultValue: nil)\n    static var supportPath: String?\n    \n  \n\n}\n"
  },
  {
    "path": "Aerial/Source/Models/Prefs/PrefsDisplays.swift",
    "content": "//\n//  PrefsDisplays.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 21/01/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Foundation\n\nenum DisplayMode: Int {\n    case allDisplays, mainOnly, secondaryOnly, selection\n}\n\nenum AspectMode: Int {\n    case fill, fit\n}\n\nenum ViewingMode: Int {\n    case independent, cloned, spanned, mirrored\n}\n\nstruct PrefsDisplays {\n    // Display Mode\n    @SimpleStorage(key: \"newDisplayMode\", defaultValue: DisplayMode.allDisplays.rawValue)\n    static var intDisplayMode: Int\n\n    // We wrap in a separate value, as we can't store an enum as a Codable in\n    // macOS < 10.15\n    static var displayMode: DisplayMode {\n        get {\n            return DisplayMode(rawValue: intDisplayMode)!\n        }\n        set(value) {\n            intDisplayMode = value.rawValue\n        }\n    }\n\n    // Viewing Mode \n    @SimpleStorage(key: \"newViewingMode\", defaultValue: ViewingMode.independent.rawValue)\n    static var intViewingMode: Int\n\n    // We wrap in a separate value, as we can't store an enum as a Codable in\n    // macOS < 10.15\n    static var viewingMode: ViewingMode {\n        get {\n            return ViewingMode(rawValue: intViewingMode)!\n        }\n        set(value) {\n            intViewingMode = value.rawValue\n        }\n    }\n\n    // Aspect Mode\n    @SimpleStorage(key: \"aspectMode\", defaultValue: AspectMode.fill.rawValue)\n    static var intAspectMode: Int\n\n    // We wrap in a separate value, as we can't store an enum as a Codable in\n    // macOS < 10.15\n    static var aspectMode: AspectMode {\n        get {\n            return AspectMode(rawValue: intAspectMode)!\n        }\n        set(value) {\n            intAspectMode = value.rawValue\n        }\n    }\n\n    // Display margins\n    @SimpleStorage(key: \"displayMarginsAdvanced\", defaultValue: false)\n    static var displayMarginsAdvanced: Bool\n\n    @SimpleStorage(key: \"horizontalMargin\", defaultValue: 0)\n    static var horizontalMargin: Double\n\n    @SimpleStorage(key: \"verticalMargin\", defaultValue: 0)\n    static var verticalMargin: Double\n\n\n\n\n    // Advanced margins are stored as a string\n    @SimpleStorage(key: \"advancedMargins\", defaultValue: \"\")\n    static var advancedMargins: String\n    \n    @SimpleStorage(key: \"dimBrightness\", defaultValue: false)\n    static var dimBrightness: Bool\n    \n    @SimpleStorage(key: \"dimOnlyAtNight\", defaultValue: false)\n    static var dimOnlyAtNight: Bool\n    @SimpleStorage(key: \"dimOnlyOnBattery\", defaultValue: false)\n    static var dimOnlyOnBattery: Bool\n    \n    @SimpleStorage(key: \"overrideDimInMinutes\", defaultValue: false)\n    static var overrideDimInMinutes: Bool\n\n    @SimpleStorage(key: \"startDim\", defaultValue: 0.5)\n    static var startDim: Double\n    @SimpleStorage(key: \"endDim\", defaultValue: 0.0)\n    static var endDim: Double\n    @SimpleStorage(key: \"dimInMinutes\", defaultValue: 30)\n    static var dimInMinutes: Int\n}\n\nstruct PrefsDisplaysDesktop {\n    // Display Mode\n    @SimpleStorage(key: \"newDisplayMode\", defaultValue: DisplayMode.allDisplays.rawValue)\n    static var intDisplayMode: Int\n\n    // We wrap in a separate value, as we can't store an enum as a Codable in\n    // macOS < 10.15\n    static var displayMode: DisplayMode {\n        get {\n            return DisplayMode(rawValue: intDisplayMode)!\n        }\n        set(value) {\n            intDisplayMode = value.rawValue\n        }\n    }\n\n    // Viewing Mode \n    @SimpleStorage(key: \"newViewingMode\", defaultValue: ViewingMode.independent.rawValue)\n    static var intViewingMode: Int\n\n    // We wrap in a separate value, as we can't store an enum as a Codable in\n    // macOS < 10.15\n    static var viewingMode: ViewingMode {\n        get {\n            return ViewingMode(rawValue: intViewingMode)!\n        }\n        set(value) {\n            intViewingMode = value.rawValue\n        }\n    }\n\n    // Aspect Mode\n    @SimpleStorage(key: \"aspectMode\", defaultValue: AspectMode.fill.rawValue)\n    static var intAspectMode: Int\n\n    // We wrap in a separate value, as we can't store an enum as a Codable in\n    // macOS < 10.15\n    static var aspectMode: AspectMode {\n        get {\n            return AspectMode(rawValue: intAspectMode)!\n        }\n        set(value) {\n            intAspectMode = value.rawValue\n        }\n    }\n\n    // Display margins\n    @SimpleStorage(key: \"displayMarginsAdvanced\", defaultValue: false)\n    static var displayMarginsAdvanced: Bool\n\n    @SimpleStorage(key: \"horizontalMargin\", defaultValue: 0)\n    static var horizontalMargin: Double\n\n    @SimpleStorage(key: \"verticalMargin\", defaultValue: 0)\n    static var verticalMargin: Double\n}"
  },
  {
    "path": "Aerial/Source/Models/Prefs/PrefsInfo.swift",
    "content": "//\n//  PrefsInfo.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 16/12/2019.\n//  Copyright © 2019 Guillaume Louel. All rights reserved.\n//\n\nimport Foundation\nimport ScreenSaver\n\nprotocol CommonInfo {\n    var isEnabled: Bool { get set }\n    var fontName: String { get set }\n    var fontSize: Double { get set }\n    var corner: InfoCorner { get set }\n    var displays: InfoDisplays { get set }\n}\n\n// Helper Enums for the common infos\nenum InfoCorner: Int, Codable, CaseIterable {\n    case topLeft, topCenter, topRight, bottomLeft, bottomCenter, bottomRight, screenCenter, random, absTopRight\n}\n\nenum InfoDisplays: Int, Codable {\n    case allDisplays, mainOnly, secondaryOnly\n}\n\nenum InfoTime: Int, Codable {\n    case always, tenSeconds\n}\n\nenum InfoClockFormat: Int, Codable {\n    case tdefault, t24hours, t12hours, custom\n}\n\nenum InfoDate: Int, Codable {\n    case textual, compact, custom\n}\n\nenum InfoIconText: Int, Codable {\n    case text, icon\n}\n\nenum InfoCountdownMode: Int, Codable {\n    case preciseDate, timeOfDay\n}\n\nenum InfoLocationMode: Int, Codable {\n    case useCurrent, manuallySpecify\n}\n\nenum InfoDegree: Int, Codable {\n    case celsius, fahrenheit\n}\n\nenum InfoIconsWeather: Int, Codable {\n    case flat, colorflat, oweather\n}\n\n// The various info types available\nenum InfoType: String, Codable {\n    case location, message, clock, date, battery, updates, weather, countdown, timer, music\n}\n\nenum InfoMessageType: Int, Codable {\n    case text, shell, textfile\n}\n\nenum InfoRefreshPeriodicity: Int, Codable {\n    case never, tenseconds, thirtyseconds, oneminute, fiveminutes, tenminutes\n}\n\nenum InfoWeatherMode: Int, Codable {\n    case current, forecast6hours, forecast3days, forecast5days\n}\n\nenum InfoWeatherWind: Int, Codable {\n    case kph, mps\n}\n\n// swiftlint:disable:next type_body_length\nstruct PrefsInfo {\n    struct Location: CommonInfo, Codable {\n        var isEnabled: Bool\n        var fontName: String\n        var fontSize: Double\n        var corner: InfoCorner\n        var displays: InfoDisplays\n        var time: InfoTime\n    }\n\n    struct Message: CommonInfo, Codable {\n        var isEnabled: Bool\n        var fontName: String\n        var fontSize: Double\n        var corner: InfoCorner\n        var displays: InfoDisplays\n        var message: String\n        var shellScript: String\n        var textFile: String\n        var messageType: InfoMessageType\n        var refreshPeriodicity: InfoRefreshPeriodicity\n    }\n\n    struct Clock: CommonInfo, Codable {\n        var isEnabled: Bool\n        var fontName: String\n        var fontSize: Double\n        var corner: InfoCorner\n        var displays: InfoDisplays\n        var showSeconds: Bool\n        var hideAmPm: Bool\n        var clockFormat: InfoClockFormat\n    }\n\n    struct IDate: CommonInfo, Codable {\n        var isEnabled: Bool\n        var fontName: String\n        var fontSize: Double\n        var corner: InfoCorner\n        var displays: InfoDisplays\n        var format: InfoDate\n        var withYear: Bool\n    }\n\n    struct Weather: CommonInfo, Codable {\n        var isEnabled: Bool\n        var fontName: String\n        var fontSize: Double\n        var corner: InfoCorner\n        var displays: InfoDisplays\n        var locationMode: InfoLocationMode\n        var locationString: String\n        var degree: InfoDegree\n        var icons: InfoIconsWeather\n        var mode: InfoWeatherMode\n        var showHumidity: Bool\n        var showWind: Bool\n        var showCity: Bool\n    }\n\n    struct Battery: CommonInfo, Codable {\n        var isEnabled: Bool\n        var fontName: String\n        var fontSize: Double\n        var corner: InfoCorner\n        var displays: InfoDisplays\n        var mode: InfoIconText\n        var disableWhenFull: Bool\n    }\n\n    struct Updates: CommonInfo, Codable {\n        var isEnabled: Bool\n        var fontName: String\n        var fontSize: Double\n        var corner: InfoCorner\n        var displays: InfoDisplays\n        var betaReset: Bool // This is useless, just to reload default settings for users of 1.7.2 early betas\n    }\n\n    struct Countdown: CommonInfo, Codable {\n        var isEnabled: Bool\n        var fontName: String\n        var fontSize: Double\n        var corner: InfoCorner\n        var displays: InfoDisplays\n        var mode: InfoCountdownMode\n        var targetDate: Date\n        var enforceInterval: Bool\n        var triggerDate: Date\n        var showSeconds: Bool\n    }\n\n    struct Timer: CommonInfo, Codable {\n        var isEnabled: Bool\n        var fontName: String\n        var fontSize: Double\n        var corner: InfoCorner\n        var displays: InfoDisplays\n        var duration: Date\n        var showSeconds: Bool\n        var disableWhenElapsed: Bool\n        var replaceWithMessage: Bool\n        var customMessage: String\n    }\n\n    struct Music: CommonInfo, Codable {\n        var isEnabled: Bool\n        var fontName: String\n        var fontSize: Double\n        var corner: InfoCorner\n        var displays: InfoDisplays\n    }\n\n    // Our array of Info layers. User can reorder the array, and we may periodically add new Info types\n    @Storage(key: \"layers\", defaultValue: [ .message, .clock, .date, .location, .battery, .updates, .weather, .countdown, .timer])\n    static var layers: [InfoType]\n\n    // Location information\n    @Storage(key: \"LayerLocation\", defaultValue: Location(isEnabled: true,\n                                                           fontName: \"Helvetica Neue Medium\",\n                                                           fontSize: 28,\n                                                           corner: .random,\n                                                           displays: .allDisplays,\n                                                           time: .always))\n    static var location: Location\n\n    // Custom string message\n    @Storage(key: \"LayerMessage\", defaultValue: Message(isEnabled: false,\n                                                         fontName: \"Helvetica Neue Medium\",\n                                                         fontSize: 20,\n                                                         corner: .topCenter,\n                                                         displays: .allDisplays,\n                                                         message: \"Hello there!\",\n                                                         shellScript: \"\",\n                                                         textFile: \"\",\n                                                         messageType: .text,\n                                                         refreshPeriodicity: .tenminutes))\n    static var message: Message\n\n    // Clock\n    @Storage(key: \"LayerClock\", defaultValue: Clock(isEnabled: true,\n                                                     fontName: \"Helvetica Neue Medium\",\n                                                     fontSize: 50,\n                                                     corner: .bottomLeft,\n                                                     displays: .allDisplays,\n                                                     showSeconds: true,\n                                                     hideAmPm: false,\n                                                     clockFormat: .tdefault))\n    static var clock: Clock\n\n    // Date\n    @Storage(key: \"LayerDate\", defaultValue: IDate(isEnabled: false,\n                                                     fontName: \"Helvetica Neue Thin\",\n                                                     fontSize: 25,\n                                                     corner: .bottomLeft,\n                                                     displays: .allDisplays,\n                                                     format: .textual,\n                                                     withYear: false))\n    static var date: IDate\n\n    // Battery\n    @Storage(key: \"LayerBattery\", defaultValue: Battery(isEnabled: false,\n                                                     fontName: \"Helvetica Neue Medium\",\n                                                     fontSize: 20,\n                                                     corner: .topRight,\n                                                     displays: .allDisplays,\n                                                     mode: .icon,\n                                                     disableWhenFull: false))\n    static var battery: Battery\n\n    // Updates\n    @Storage(key: \"LayerUpdates\", defaultValue: Updates(isEnabled: true,\n                                                     fontName: \"Helvetica Neue Medium\",\n                                                     fontSize: 20,\n                                                     corner: .topRight,\n                                                     displays: .allDisplays,\n                                                     betaReset: true))\n    static var updates: Updates\n\n    // Weather\n    @Storage(key: \"LayerWeather\", defaultValue: Weather(isEnabled: false,\n                                                        fontName: \"Helvetica Neue Medium\",\n                                                        fontSize: 40,\n                                                        corner: .topRight,\n                                                        displays: .allDisplays,\n                                                        locationMode: .manuallySpecify,\n                                                        locationString: \"\",\n                                                        degree: .celsius,\n                                                        icons: isMacOS11() ? .colorflat : .flat,\n                                                        mode: .current,\n                                                        showHumidity: true,\n                                                        showWind: true,\n                                                        showCity: true))\n    static var weather: Weather\n\n    // Text fade in/out mode\n    @SimpleStorage(key: \"weatherWindMode\", defaultValue: InfoWeatherWind.kph.rawValue)\n    static var intWeatherWindMode: Int\n\n    // We wrap in a separate value, as we can't store an enum as a Codable in\n    // macOS < 10.15\n    static var weatherWindMode: InfoWeatherWind {\n        get {\n            return InfoWeatherWind(rawValue: intWeatherWindMode)!\n        }\n        set(value) {\n            intWeatherWindMode = value.rawValue\n        }\n    }\n\n    // Music\n    @Storage(key: \"LayerMusic\", defaultValue: Music(isEnabled: true,\n                                                     fontName: \"Helvetica Neue Medium\",\n                                                     fontSize: 20,\n                                                     corner: .topRight,\n                                                     displays: .allDisplays))\n    static var music: Music\n\n    // Apple Music storefront to be used\n    @SimpleStorage(key: \"appleMusicStoreFront\", defaultValue: \"United States\")\n    static var appleMusicStoreFront: String\n\n    // Apple Music storefront to be used\n    @SimpleStorage(key: \"musicProvider\", defaultValue: \"Apple Music\")\n    static var musicProvider: String\n\n    // Countdown\n    @Storage(key: \"LayerCountdown\", defaultValue: Countdown(isEnabled: false,\n                                                     fontName: \"Helvetica Neue Medium\",\n                                                     fontSize: 100,\n                                                     corner: .screenCenter,\n                                                     displays: .allDisplays,\n                                                     mode: .timeOfDay,\n                                                     targetDate: Date(),\n                                                     enforceInterval: false,\n                                                     triggerDate: Date(),\n                                                     showSeconds: true))\n    static var countdown: Countdown\n\n    // Timer\n    @Storage(key: \"LayerTimer\", defaultValue: Timer(isEnabled: false,\n                                                    fontName: \"Helvetica Neue Medium\",\n                                                    fontSize: 100,\n                                                    corner: .screenCenter,\n                                                    displays: .allDisplays,\n                                                    duration: Date(timeIntervalSince1970: 300),\n                                                    showSeconds: true,\n                                                    disableWhenElapsed: true,\n                                                    replaceWithMessage: false,\n                                                    customMessage: \"\"))\n\n    static var timer: Timer\n\n    @SimpleStorage(key: \"customDateFormat\", defaultValue: \"\")\n    static var customDateFormat: String\n\n    @SimpleStorage(key: \"customTimeFormat\", defaultValue: \"\")\n    static var customTimeFormat: String\n\n    // MARK: - Advanced text settings\n\n    // Text fade in/out mode\n    @SimpleStorage(key: \"fadeModeText\", defaultValue: FadeMode.t1.rawValue)\n    static var intFadeModeText: Int\n\n    // We wrap in a separate value, as we can't store an enum as a Codable in\n    // macOS < 10.15\n    static var fadeModeText: FadeMode {\n        get {\n            return FadeMode(rawValue: intFadeModeText)!\n        }\n        set(value) {\n            intFadeModeText = value.rawValue\n        }\n    }\n\n    // Fast rendering mode\n    @SimpleStorage(key: \"highQualityTextRendering\", defaultValue: HardwareDetection.sharedInstance.isAppleSilicon())\n    static var highQualityTextRendering: Bool\n\n    // Override margins\n    @SimpleStorage(key: \"overrideMargins\", defaultValue: false)\n    static var overrideMargins: Bool\n\n    // Hide overlays under Companion\n    @SimpleStorage(key: \"hideUnderCompanion\", defaultValue: true)\n    static var hideUnderCompanion: Bool\n\n    \n    @SimpleStorage(key: \"marginX\", defaultValue: 50)\n    static var marginX: Int\n    @SimpleStorage(key: \"marginY\", defaultValue: 50)\n    static var marginY: Int\n\n    // MARK: - Shadows\n    // Shadow radius\n    @SimpleStorage(key: \"shadowRadius\", defaultValue: 2)\n    static var shadowRadius: Int\n    @SimpleStorage(key: \"shadowOpacity\", defaultValue: 1.0)\n    static var shadowOpacity: Float\n    @SimpleStorage(key: \"shadowOffsetX\", defaultValue: 0.0)\n    static var shadowOffsetX: CGFloat\n    @SimpleStorage(key: \"shadowOffsetY\", defaultValue: -3.0)\n    static var shadowOffsetY: CGFloat\n\n    static func isMacOS11() -> Bool {\n        if #available(macOS 11.0, *) {\n            return true\n        } else {\n            return false\n        }\n    }\n\n    // MARK: - Helpers\n    // Helper to quickly access a given struct (read-only as we return a copy of the struct)\n    static func ofType(_ type: InfoType) -> CommonInfo {\n        switch type {\n        case .location:\n            return location\n        case .message:\n            return message\n        case .clock:\n            return clock\n        case .date:\n            return date\n        case .battery:\n            return battery\n        case .updates:\n            return updates\n        case .weather:\n            return weather\n        case .countdown:\n            return countdown\n        case .timer:\n            return timer\n        case .music:\n            return music\n        }\n    }\n\n    // Helpers to store the value for the common properties of all info layers\n    static func setEnabled(_ type: InfoType, value: Bool) {\n        switch type {\n        case .location:\n            location.isEnabled = value\n        case .message:\n            message.isEnabled = value\n        case .clock:\n            clock.isEnabled = value\n        case .date:\n            date.isEnabled = value\n        case .battery:\n            battery.isEnabled = value\n        case .updates:\n            updates.isEnabled = value\n        case .weather:\n            weather.isEnabled = value\n        case .countdown:\n            countdown.isEnabled = value\n        case .timer:\n            timer.isEnabled = value\n        case .music:\n            music.isEnabled = value\n        }\n    }\n\n    static func setFontName(_ type: InfoType, name: String) {\n        switch type {\n        case .location:\n            location.fontName = name\n        case .message:\n            message.fontName = name\n        case .clock:\n            clock.fontName = name\n        case .date:\n            date.fontName = name\n        case .battery:\n            battery.fontName = name\n        case .updates:\n            updates.fontName = name\n        case .weather:\n            weather.fontName = name\n        case .countdown:\n            countdown.fontName = name\n        case .timer:\n            timer.fontName = name\n        case .music:\n            music.fontName = name\n        }\n    }\n\n    static func setFontSize(_ type: InfoType, size: Double) {\n        switch type {\n        case .location:\n            location.fontSize = size\n        case .message:\n            message.fontSize = size\n        case .clock:\n            clock.fontSize = size\n        case .date:\n            date.fontSize = size\n        case .battery:\n            battery.fontSize = size\n        case .updates:\n            updates.fontSize = size\n        case .weather:\n            weather.fontSize = size\n        case .countdown:\n            countdown.fontSize = size\n        case .timer:\n            timer.fontSize = size\n        case .music:\n            music.fontSize = size\n        }\n    }\n\n    static func setCorner(_ type: InfoType, corner: InfoCorner) {\n        switch type {\n        case .location:\n            location.corner = corner\n        case .message:\n            message.corner = corner\n        case .clock:\n            clock.corner = corner\n        case .date:\n            date.corner = corner\n        case .battery:\n            battery.corner = corner\n        case .updates:\n            updates.corner = corner\n        case .weather:\n            weather.corner = corner\n        case .countdown:\n            countdown.corner = corner\n        case .timer:\n            timer.corner = corner\n        case .music:\n            music.corner = corner\n        }\n\n    }\n    static func setDisplayMode(_ type: InfoType, mode: InfoDisplays) {\n        switch type {\n        case .location:\n            location.displays = mode\n        case .message:\n            message.displays = mode\n        case .clock:\n            clock.displays = mode\n        case .date:\n            date.displays = mode\n        case .battery:\n            battery.displays = mode\n        case .updates:\n            updates.displays = mode\n        case .weather:\n            weather.displays = mode\n        case .countdown:\n            countdown.displays = mode\n        case .timer:\n            timer.displays = mode\n        case .music:\n            music.displays = mode\n        }\n    }\n\n    // This may be a temp workaround, will depend on where it goes\n    // We periodically add new types so we must add them\n    static func updateLayerList() {\n        if !PrefsInfo.layers.contains(.battery) {\n            PrefsInfo.layers.append(.battery)\n        }\n\n        if !PrefsInfo.layers.contains(.countdown) {\n            PrefsInfo.layers.append(.countdown)\n        }\n\n        if !PrefsInfo.layers.contains(.timer) {\n            PrefsInfo.layers.append(.timer)\n        }\n\n        if !PrefsInfo.layers.contains(.date) {\n            PrefsInfo.layers.append(.date)\n        }\n\n        if !PrefsInfo.layers.contains(.weather) {\n            PrefsInfo.layers.append(.weather)\n        }\n\n        if !PrefsInfo.layers.contains(.music) {\n            PrefsInfo.layers.append(.music)\n        }\n\n        // Annnd for backward compatibility with 1.7.2 betas, remove the updates that was once here ;)\n        if PrefsInfo.layers.contains(.updates) {\n            PrefsInfo.layers.remove(at: PrefsInfo.layers.firstIndex(of: .updates)!)\n        }\n    }\n}\n\n// This retrieves/store any type of property in our plist\n@propertyWrapper struct Storage<T: Codable> {\n    private let key: String\n    private let defaultValue: T\n    private let module = \"com.JohnCoates.Aerial\"\n    private let bundleID = Aerial.helper.getPreferencesDirectory() + \"com.glouel.Aerial\"\n    \n    init(key: String, defaultValue: T) {\n        self.key = key\n        self.defaultValue = defaultValue\n    }\n\n    var wrappedValue: T {\n        get {\n            if #available(OSX 10.15, *) {\n                if let userDefaults = UserDefaults(suiteName: bundleID) {\n                    // We shoot for a string in the new system\n                    if let jsonString = userDefaults.string(forKey: key) {\n                        guard let jsonData = jsonString.data(using: .utf8) else {\n                            return defaultValue\n                        }\n                        guard let value = try? JSONDecoder().decode(T.self, from: jsonData) else {\n                            return defaultValue\n                        }\n                        return value\n                    } else {\n                        // Old time users may have the prefs stored as a data blob though\n                        if let data = userDefaults.object(forKey: key) as? Data {\n                            let value = try? JSONDecoder().decode(T.self, from: data)\n                            return value ?? defaultValue\n                        } else {\n                            return defaultValue\n                        }\n                    }\n                }\n            } else {\n                if let userDefaults = ScreenSaverDefaults(forModuleWithName: module) {\n                    // We shoot for a string in the new system\n                    if let jsonString = userDefaults.string(forKey: key) {\n                        guard let jsonData = jsonString.data(using: .utf8) else {\n                            return defaultValue\n                        }\n                        guard let value = try? JSONDecoder().decode(T.self, from: jsonData) else {\n                            return defaultValue\n                        }\n                        return value\n                    } else {\n                        // Old time users may have the prefs stored as a data blob though\n                        if let data = userDefaults.object(forKey: key) as? Data {\n                            let value = try? JSONDecoder().decode(T.self, from: data)\n                            return value ?? defaultValue\n                        } else {\n                            return defaultValue\n                        }\n                    }\n                }\n            }\n\n            return defaultValue\n        }\n        set {\n            let encoder = JSONEncoder()\n            if #available(OSX 10.13, *) {\n                encoder.outputFormatting = [.prettyPrinted, .sortedKeys]\n            } else {\n                encoder.outputFormatting = [.prettyPrinted]\n            }\n\n            let jsonData = try? encoder.encode(newValue)\n            let jsonString = String(bytes: jsonData!, encoding: .utf8)\n\n            if #available(OSX 10.15, *) {\n                if let userDefaults = UserDefaults(suiteName: bundleID) {\n                    // Set value to UserDefaults\n                    userDefaults.set(jsonString, forKey: key)\n\n                    // We force the sync so the settings are automatically saved\n                    // This is needed as the System Preferences instance of Aerial\n                    // is a separate instance from the screensaver ones\n                    userDefaults.synchronize()\n                } else {\n                    errorLog(\"UserDefaults set failed for \\(key)\")\n                }\n            } else {\n                if let userDefaults = ScreenSaverDefaults(forModuleWithName: module) {\n                    // Set value to UserDefaults\n                    userDefaults.set(jsonString, forKey: key)\n\n                    // We force the sync so the settings are automatically saved\n                    // This is needed as the System Preferences instance of Aerial\n                    // is a separate instance from the screensaver ones\n                    userDefaults.synchronize()\n                } else {\n                    errorLog(\"UserDefaults set failed for \\(key)\")\n                }\n            }\n        }\n    }\n}\n\n// This retrieves store \"simple\" types that are natively storable on plists\n@propertyWrapper struct SimpleStorage<T> {\n    private let key: String\n    private let defaultValue: T\n    private let module = \"com.JohnCoates.Aerial\"\n    private let bundleID = Aerial.helper.getPreferencesDirectory() + \"com.glouel.Aerial\"\n    \n    init(key: String, defaultValue: T) {\n        self.key = key\n        self.defaultValue = defaultValue\n    }\n\n    var wrappedValue: T {\n        get {\n            if #available(OSX 10.15, *) {\n                if let userDefaults = UserDefaults(suiteName: bundleID) {\n                    return userDefaults.object(forKey: key) as? T ?? defaultValue\n                }\n            } else {\n                if let userDefaults = ScreenSaverDefaults(forModuleWithName: module) {\n                    return userDefaults.object(forKey: key) as? T ?? defaultValue\n                }\n            }\n\n            return defaultValue\n        }\n        set {\n            if #available(OSX 10.15, *) {\n                if let userDefaults = UserDefaults(suiteName: bundleID) {\n                    userDefaults.set(newValue, forKey: key)\n                    userDefaults.synchronize()\n                }\n            } else {\n                if let userDefaults = ScreenSaverDefaults(forModuleWithName: module) {\n                    userDefaults.set(newValue, forKey: key)\n                    userDefaults.synchronize()\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Models/Prefs/PrefsTime.swift",
    "content": "//\n//  PrefsTime.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 21/01/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Foundation\n\nenum TimeMode: Int {\n    case disabled, nightShift, manual, lightDarkMode, coordinates, locationService\n}\n\nenum SolarMode: Int {\n    case strict, official, civil, nautical, astronomical\n}\n\nstruct PrefsTime {\n    // Time Mode\n    @SimpleStorage(key: \"timeMode\", defaultValue: TimeMode.disabled.rawValue)\n    static var intTimeMode: Int\n\n    // We wrap in a separate value, as we can't store an enum as a Codable in\n    // macOS < 10.15\n    static var timeMode: TimeMode {\n        get {\n            return TimeMode(rawValue: intTimeMode)!\n        }\n        set(value) {\n            intTimeMode = value.rawValue\n        }\n    }\n\n    // Manually specified sunrise/sunsets\n    @SimpleStorage(key: \"manualSunrise\", defaultValue: \"09:00\")\n    static var manualSunrise: String\n\n    @SimpleStorage(key: \"manualSunset\", defaultValue: \"19:00\")\n    static var manualSunset: String\n\n    // Manually specified latitude/longitude (strings)\n    @SimpleStorage(key: \"latitude\", defaultValue: \"\")\n    static var latitude: String\n\n    @SimpleStorage(key: \"longitude\", defaultValue: \"\")\n    static var longitude: String\n\n    // Solar Mode\n    @SimpleStorage(key: \"solarMode\", defaultValue: SolarMode.official.rawValue)\n    static var intSolarMode: Int\n\n    // Prefs sunrise/sunset duration\n    @SimpleStorage(key: \"sunEventWindow\", defaultValue: 60*180)\n    static var sunEventWindow: Int\n\n    // We wrap in a separate value, as we can't store an enum as a Codable in\n    // macOS < 10.15\n    static var solarMode: SolarMode {\n        get {\n            return SolarMode(rawValue: intSolarMode)!\n        }\n        set(value) {\n            intSolarMode = value.rawValue\n        }\n    }\n\n    // Override on macOS dark mode\n    @SimpleStorage(key: \"darkModeNightOverride\", defaultValue: false)\n    static var darkModeNightOverride: Bool\n\n    // Last successful coordinates, we're going to save those so we can reuse them if we can't get\n    // Anything from Location Services (laptop plugged on ethernet with wifi off is the scenario)\n    @SimpleStorage(key: \"cachedLatitude\", defaultValue: 0)\n    static var cachedLatitude: Double\n\n    @SimpleStorage(key: \"cachedLongitude\", defaultValue: 0)\n    static var cachedLongitude: Double\n\n    // Last geocoded string, the result is stored in cachedLatitude/cachedLongitude above\n    @SimpleStorage(key: \"geocodedString\", defaultValue: \"\")\n    static var geocodedString: String\n\n}\n"
  },
  {
    "path": "Aerial/Source/Models/Prefs/PrefsUpdates.swift",
    "content": "//\n//  PrefsUpdates.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 16/02/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Foundation\n\nenum UpdateMode: Int {\n    case notify, install\n}\n\nstruct PrefsUpdates {\n    // Update Mode when the screensaver runs (notify or install)\n    @SimpleStorage(key: \"checkForUpdates\", defaultValue: true)\n    static var checkForUpdates: Bool\n\n    // Update Mode when the screensaver runs (notify or install)\n    @SimpleStorage(key: \"sparkleUpdateMode\", defaultValue: getDefaultUpdateMode())\n    static var intSparkleUpdateMode: Int\n\n    // We wrap in a separate value, as we can't store an enum as a Codable in\n    // macOS < 10.15\n    static var sparkleUpdateMode: UpdateMode {\n        get {\n            return UpdateMode(rawValue: intSparkleUpdateMode)!\n        }\n        set(value) {\n            intSparkleUpdateMode = value.rawValue\n        }\n    }\n\n    // On Catalina, we notify by default, on previous OSes we install by default\n    static func getDefaultUpdateMode() -> Int {\n        if #available(OSX 10.15, *) {\n            return UpdateMode.notify.rawValue\n        } else {\n            return UpdateMode.install.rawValue\n        }\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Models/Prefs/PrefsVideos.swift",
    "content": "//\n//  PrefsVideos.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 23/12/2019.\n//  Copyright © 2019 Guillaume Louel. All rights reserved.\n//\n\nimport Foundation\n\nenum VideoFormat: Int, Codable, CaseIterable {\n    case v1080pH264, v1080pHEVC, v1080pHDR, v4KHEVC, v4KHDR, v4KSDR240\n}\n\nenum OnBatteryMode: Int, Codable {\n    case keepEnabled, alwaysDisabled, disableOnLow\n}\n\nenum FadeMode: Int {\n    // swiftlint:disable:next identifier_name\n    case disabled, t0_5, t1, t2\n}\n\nenum ShouldPlay: Int {\n    case everything, favorites, location, time, scene, source, collection\n}\n\nenum NewShouldPlay: Int {\n    case location, favorites, time, scene, source\n}\n\nenum RefreshPeriodicity: Int {\n    case weekly, monthly, never\n}\n\nstruct PrefsVideos {\n    // Main playback mode after v2.5\n    @SimpleStorage(key: \"intNewShouldPlay\", defaultValue: NewShouldPlay.location.rawValue)\n    static var intNewShouldPlay: Int\n\n    // We wrap in a separate value, as we can't store an enum as a Codable in\n    // macOS < 10.15\n    static var newShouldPlay: NewShouldPlay {\n        get {\n            return NewShouldPlay(rawValue: intNewShouldPlay)!\n        }\n        set(value) {\n            intNewShouldPlay = value.rawValue\n        }\n    }\n\n    // Main playback mode (deprecated in 2.5)\n    @SimpleStorage(key: \"intShouldPlay\", defaultValue: ShouldPlay.everything.rawValue)\n    static var intShouldPlay: Int\n\n    // We wrap in a separate value, as we can't store an enum as a Codable in\n    // macOS < 10.15\n    static var shouldPlay: ShouldPlay {\n        get {\n            return ShouldPlay(rawValue: intShouldPlay)!\n        }\n        set(value) {\n            intShouldPlay = value.rawValue\n        }\n    }\n\n    // Starting with v2.5\n    @SimpleStorage(key: \"newShouldPlayString\", defaultValue: [])\n    static var newShouldPlayString: [String]\n\n    // Deprecated in v2.5\n    @SimpleStorage(key: \"shouldPlayString\", defaultValue: \"\")\n    static var shouldPlayString: String\n\n    // What do we do on battery ?\n    @SimpleStorage(key: \"intOnBatteryMode\", defaultValue: OnBatteryMode.keepEnabled.rawValue)\n    static var intOnBatteryMode: Int\n\n    // We wrap in a separate value, as we can't store an enum as a Codable in\n    // macOS < 10.15\n    static var onBatteryMode: OnBatteryMode {\n        get {\n            return OnBatteryMode(rawValue: intOnBatteryMode)!\n        }\n        set(value) {\n            intOnBatteryMode = value.rawValue\n        }\n    }\n\n    // Internal storage for video format\n    @SimpleStorage(key: \"intVideoFormat\", defaultValue: VideoFormat.v1080pH264.rawValue)\n    static var intVideoFormat: Int\n\n    // We wrap in a separate value, as we can't store an enum as a Codable in\n    // macOS < 10.15\n    static var videoFormat: VideoFormat {\n        get {\n            return VideoFormat(rawValue: intVideoFormat)!\n        }\n        set(value) {\n            intVideoFormat = value.rawValue\n        }\n    }\n\n    // Video fade in/out mode\n    @SimpleStorage(key: \"fadeMode\", defaultValue: FadeMode.t1.rawValue)\n    static var intFadeMode: Int\n\n    // We wrap in a separate value, as we can't store an enum as a Codable in\n    // macOS < 10.15\n    static var fadeMode: FadeMode {\n        get {\n            return FadeMode(rawValue: intFadeMode)!\n        }\n        set(value) {\n            intFadeMode = value.rawValue\n        }\n    }\n\n    // How often should we look for new videos ?\n    @SimpleStorage(key: \"intRefreshPeriodicity\",\n                   defaultValue: PrefsCache.enableManagement\n                    ? RefreshPeriodicity.monthly.rawValue\n                    : RefreshPeriodicity.never.rawValue)\n    static var intRefreshPeriodicity: Int\n\n    // We wrap in a separate value, as we can't store an enum as a Codable in\n    // macOS < 10.15\n    static var refreshPeriodicity: RefreshPeriodicity {\n        get {\n            return RefreshPeriodicity(rawValue: intRefreshPeriodicity)!\n        }\n        set(value) {\n            intRefreshPeriodicity = value.rawValue\n        }\n    }\n\n    // Allow video skips with right arrow key (on supporting OSes)\n    @SimpleStorage(key: \"allowSkips\", defaultValue: true)\n    static var allowSkips: Bool\n\n    @SimpleStorage(key: \"sourcesEnabled\", defaultValue: [\"macOS 26\": true,\n                                                         \"tvOS 16\": false,\n                                                         \"tvOS 13\": false])\n    static var enabledSources: [String: Bool]\n\n    // Favorites (we use the video ID)\n    @SimpleStorage(key: \"favorites\", defaultValue: [])\n    static var favorites: [String]\n\n    // Hidden list (same)\n    @SimpleStorage(key: \"hidden\", defaultValue: [])\n    static var hidden: [String]\n\n    @SimpleStorage(key: \"vibrance\", defaultValue: [:])\n    static var vibrance: [String: Double]\n\n    @SimpleStorage(key: \"durationCache\", defaultValue: [:])\n    static var durationCache: [String: Double]\n\n    @SimpleStorage(key: \"playbackSpeed\", defaultValue: [:])\n    static var playbackSpeed: [String: Float]\n\n    @SimpleStorage(key: \"globalVibrance\", defaultValue: 0)\n    static var globalVibrance: Double\n\n    @SimpleStorage(key: \"allowPerVideoVibrance\", defaultValue: false)\n    static var allowPerVideoVibrance: Bool\n\n    static private func defaultLastVideoCheck() -> String {\n        let dateFormatter = DateFormatter()\n        let current = Date(timeIntervalSinceReferenceDate: -123456789.0)\n        dateFormatter.dateFormat = \"yyyy-MM-dd\"\n        return dateFormatter.string(from: current)\n    }\n\n    @SimpleStorage(key: \"lastVideoCheck\", defaultValue: defaultLastVideoCheck())\n    static var lastVideoCheck: String\n\n\n    \n    static private func intervalSinceLastVideoCheck() -> TimeInterval {\n        let dateFormatter = DateFormatter()\n        dateFormatter.dateFormat = \"yyyy-MM-dd\"\n        dateFormatter.locale = Locale.init(identifier: \"en_GB\")\n        let dateObj = dateFormatter.date(from: PrefsVideos.lastVideoCheck)!\n\n        // debugLog(\"Last manifest check : \\(dateObj)\")\n\n        return dateObj.timeIntervalSinceNow\n    }\n\n    static func saveLastVideoCheck() {\n        let dateFormatter = DateFormatter()\n        let current = Date()\n        dateFormatter.dateFormat = \"yyyy-MM-dd\"\n        PrefsVideos.lastVideoCheck = dateFormatter.string(from: current)\n    }\n\n    static func shouldCheckForNewVideos() -> Bool {\n        if refreshPeriodicity == .never {\n            return false\n        }\n\n        var dayCheck = 7\n        if refreshPeriodicity == .monthly {\n            dayCheck = 30\n        }\n\n        // debugLog(\"Interval : \\(intervalSinceLastVideoCheck())\")\n        if Int(intervalSinceLastVideoCheck()) < -dayCheck * 86400 {\n            // debugLog(\"Checking for new videos\")\n            return true\n        } else {\n            // debugLog(\"No need to check for new videos\")\n            return false\n        }\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Models/SeededGenerator.swift",
    "content": "//\n//  SeededGenerator.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 21/05/2019.\n//  Copyright © 2019 John Coates. All rights reserved.\n//\n\nimport Foundation\nimport GameplayKit\n\n@available(OSX 10.11, *)\nclass SeededGenerator: RandomNumberGenerator {\n    let seed: UInt64\n    private let generator: GKMersenneTwisterRandomSource\n\n    convenience init() {\n        self.init(seed: 0)\n    }\n\n    init(seed: UInt64) {\n        self.seed = seed\n        generator = GKMersenneTwisterRandomSource(seed: seed)\n    }\n\n    func next() -> UInt64 {\n        return UInt64(abs(generator.nextInt()))\n    }\n\n    func next<T>(upperBound: T) -> T where T: FixedWidthInteger, T: UnsignedInteger {\n        return T(abs(generator.nextInt(upperBound: Int(upperBound))))\n    }\n\n    func next<T>() -> T where T: FixedWidthInteger, T: UnsignedInteger {\n        return T(abs(generator.nextInt()))\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Models/Sources/Sidebar.swift",
    "content": "//\n//  Sidebar.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 15/07/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Cocoa\n\nclass Sidebar {\n    var modern: [Any] = []\n\n    struct Header {\n        let name: String\n        let entries: [MenuEntry]\n    }\n    struct MenuEntry {\n        let name: String\n        let path: String\n    }\n\n    static let instance: Sidebar = Sidebar()\n\n    init() {\n        makeModern()\n    }\n\n    // The new modern menu in 3.0\n    func makeModern() {\n\n        modern = [\n            Header(name: \"Aerials\", entries: [\n                MenuEntry(name: \"Now Playing\", path: \"modern:nowplaying\"),\n                MenuEntry(name: \"Browse Videos\", path: \"videos:all\"),\n                MenuEntry(name: \"More Videos\", path: \"settings:sources\")\n            ]),\n            Header(name: \"Settings\", entries: [\n                MenuEntry(name: \"Time\", path: \"settings:time\"),\n                MenuEntry(name: \"Displays\", path: \"settings:displays\"),\n                MenuEntry(name: \"Brightness\", path: \"settings:brightness\"),\n                MenuEntry(name: \"Cache\", path: \"settings:cache\"),\n                MenuEntry(name: \"Overlays\", path: \"settings:overlays\"),\n                MenuEntry(name: \"Filters\", path: \"settings:filters\"),\n                // MenuEntry(name: \"Auto Updates\", path: \"settings:updates\"),\n                MenuEntry(name: \"Advanced\", path: \"settings:advanced\")\n            ]),\n            Header(name: \"Information\", entries: [\n                MenuEntry(name: \"About\", path: \"infos:about\"),\n                MenuEntry(name: \"Credits\", path: \"infos:credits\"),\n                MenuEntry(name: \"Help\", path: \"infos:help\")\n            ])\n        ]\n    }\n\n    // Helper to get the various icons for the sidebar\n    // swiftlint:disable:next cyclomatic_complexity\n    static func iconFor(_ path: String, name: String) -> NSImage? {\n        if path.starts(with: \"videos:location\") {\n            return Aerial.helper.getAccentedSymbol(\"mappin.and.ellipse\")\n        } else if path.starts(with: \"videos:cache\") && name == VideoList.instance.cacheDownloaded {\n            return Aerial.helper.getAccentedSymbol(\"internaldrive\")\n        } else if path.starts(with: \"videos:cache\") && name == VideoList.instance.cacheOnline {\n            return Aerial.helper.getAccentedSymbol(\"cloud\")\n\n        } else if path.starts(with: \"videos:time\") && name == \"Day\" {\n            return Aerial.helper.getAccentedSymbol(\"sun.max\")\n        } else if path.starts(with: \"videos:time\") && name == \"Night\" {\n            return Aerial.helper.getAccentedSymbol(\"moon.stars\")\n        } else if path.starts(with: \"videos:time\") && name == \"Sunrise\" {\n            return Aerial.helper.getAccentedSymbol(\"sunrise\")\n        } else if path.starts(with: \"videos:time\") && name == \"Sunset\" {\n            return Aerial.helper.getAccentedSymbol(\"sunset\")\n\n        } else if path.starts(with: \"videos:scene\") && name == \"Nature\" {\n            return Aerial.helper.getAccentedSymbol(\"leaf\")\n        } else if path.starts(with: \"videos:scene\") && name == \"City\" {\n            return Aerial.helper.getAccentedSymbol(\"tram.fill\")\n        } else if path.starts(with: \"videos:scene\") && name == \"Space\" {\n            return Aerial.helper.getAccentedSymbol(\"sparkles\")\n        } else if path.starts(with: \"videos:scene\") && name == \"Sea\" {\n            return Aerial.helper.getAccentedSymbol(\"helm\")\n        } else if path.starts(with: \"videos:scene\") && name == \"Beach\" {\n            return Aerial.helper.getAccentedSymbol(\"helm\")\n        } else if path.starts(with: \"videos:scene\") && name == \"Countryside\" {\n            return Aerial.helper.getAccentedSymbol(\"helm\")\n\n        } else if path.starts(with: \"videos:rotation\") {\n            return Aerial.helper.getAccentedSymbol(\"dial.min\")\n\n        } else if path.starts(with: \"videos:favorite\") {\n            return Aerial.helper.getSymbol(\"star\")\n\n        } else if path.starts(with: \"videos:hidden\") {\n            return Aerial.helper.getAccentedSymbol(\"eye.slash\")\n\n        } else if path.starts(with: \"videos:source\") {\n            return Aerial.helper.getAccentedSymbol(\"antenna.radiowaves.left.and.right\")\n\n        } else if path.starts(with: \"videos:\") {\n            return Aerial.helper.getAccentedSymbol(\"film\")\n\n        } else if path.starts(with: \"settings:sources\") {\n            return Aerial.helper.getAccentedSymbol(\"antenna.radiowaves.left.and.right\")\n        } else if path.starts(with: \"settings:time\") {\n            return Aerial.helper.getAccentedSymbol(\"clock\")\n        } else if path.starts(with: \"settings:displays\") {\n            return Aerial.helper.getAccentedSymbol(\"display.2\")\n        } else if path.starts(with: \"settings:brightness\") {\n            return Aerial.helper.getAccentedSymbol(\"sun.min\")\n        } else if path.starts(with: \"settings:cache\") {\n            return Aerial.helper.getAccentedSymbol(\"internaldrive\")\n        } else if path.starts(with: \"settings:overlays\") {\n            return Aerial.helper.getAccentedSymbol(\"text.bubble\")\n        } else if path.starts(with: \"settings:filters\") {\n            return Aerial.helper.getAccentedSymbol(\"slider.horizontal.3\")\n        } else if path.starts(with: \"settings:updates\") {\n            return Aerial.helper.getAccentedSymbol(\"arrow.down.circle\")\n        } else if path.starts(with: \"settings:advanced\") {\n            return Aerial.helper.getAccentedSymbol(\"wrench.and.screwdriver\")\n\n        } else if path.starts(with: \"infos:help\") {\n            return Aerial.helper.getAccentedSymbol(\"bubble.left.and.bubble.right\")\n        } else if path.starts(with: \"infos:credits\") {\n            return Aerial.helper.getAccentedSymbol(\"person.3\")\n        } else if path.starts(with: \"infos:about\") {\n            return Aerial.helper.getAccentedSymbol(\"info.circle\")\n\n        } else if path.starts(with: \"modern:nowplaying\") {\n            return Aerial.helper.getAccentedSymbol(\"play.circle\")\n\n        } else {\n            // For the WIP\n            return Aerial.helper.getSymbol(\"wrench\")\n        }\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Models/Sources/Source.swift",
    "content": "//\n//  Source.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 01/07/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Foundation\n\n// 10 has a different format\n// 11 is similar to 12+, but does not include pointsOfInterests\n// 12/13 share a same format, and we use that format for local videos too\nenum SourceType: Int, Codable {\n    case local, tvOS10, tvOS11, tvOS12, macOS\n}\n\nenum SourceScene: String, Codable {\n    case nature = \"Nature\", city = \"City\", space = \"Space\", sea = \"Sea\", beach = \"Beach\", countryside = \"Countryside\"\n}\n\n// swiftlint:disable:next type_body_length\nstruct Source: Codable {\n    var name: String\n    var description: String\n    var manifestUrl: String\n    var type: SourceType\n    var scenes: [SourceScene]\n    var isCachable: Bool\n    var license: String\n    var more: String\n    \n    func isEnabled() -> Bool {\n        if PrefsVideos.enabledSources.keys.contains(name) {\n            return PrefsVideos.enabledSources[name]!\n        }\n\n        // Unknown sources are enabled by default\n        return true\n    }\n\n    func diskUsage() -> Double {\n        let path = Cache.supportPath.appending(\"/\" + name)\n\n        return Cache.getDirectorySize(directory: path)\n    }\n\n    func wipeFromDisk() {\n        let path = Cache.supportPath.appending(\"/\" + name)\n\n        if FileManager.default.fileExists(atPath: path) {\n            try? FileManager.default.removeItem(atPath: path)\n        }\n    }\n\n    func setEnabled(_ enabled: Bool) {\n        PrefsVideos.enabledSources[name] = enabled\n        VideoList.instance.reloadSources()\n    }\n\n    // Is the source already cached or not ?\n    func isCached() -> Bool {\n        let fileManager = FileManager.default\n        return fileManager.fileExists(atPath: Cache.supportPath.appending(\"/\" + name + \"/entries.json\"))\n    }\n\n    func lastUpdated() -> String {\n        if isCached() {\n            var date: Date?\n            if !isCachable && type == .local {\n                date = (try? FileManager.default.attributesOfItem(atPath:\n                Cache.supportPath.appending(\"/\" + name + \"/entries.json\")))?[.modificationDate] as? Date\n            } else {\n                date = (try? FileManager.default.attributesOfItem(atPath:\n                Cache.supportPath.appending(\"/\" + name + \"/entries.json\")))?[.creationDate] as? Date\n            }\n\n            if date != nil {\n                let dateFormatter = DateFormatter()\n                dateFormatter.dateFormat = \"yyyy-MM-dd\"\n                return dateFormatter.string(from: date!)\n            } else {\n                return \"\"\n            }\n        }\n        return \"\"\n    }\n\n    // Read local entries.json and return the video assets as an array\n    // This is used to update in place the entries.json at startup when updating local sources\n    func getUnprocessedAssets() -> [VideoAsset] {\n        if isCached() {\n            do {\n                let cacheFileUrl = URL(fileURLWithPath: Cache.supportPath.appending(\"/\" + name + \"/entries.json\"))\n                let jsondata = try Data(contentsOf: cacheFileUrl)\n\n                if let videoManifest = try? newJSONDecoder().decode(VideoManifest.self, from: jsondata) {\n                    return videoManifest.assets\n                }\n\n                errorLog(\"### Could not parse manifest data\")\n                return []\n            } catch {\n                errorLog(\"\\(name) could not be opened\")\n                return []\n            }\n        } else {\n            debugLog(\"\\(name) is not cached\")\n            return []\n        }\n    }\n    \n    func getUnprocessedVideos() -> [AerialVideo] {\n        if isCached() {\n            do {\n                let cacheFileUrl = URL(fileURLWithPath: Cache.supportPath.appending(\"/\" + name + \"/entries.json\"))\n                let jsondata = try Data(contentsOf: cacheFileUrl)\n\n                return readVideoManifest(jsondata)\n            } catch {\n                errorLog(\"\\(name) could not be opened\")\n                return []\n            }\n        } else {\n            debugLog(\"\\(name) is not cached\")\n            return []\n        }\n    }\n\n    func getVideos() -> [AerialVideo] {\n        if isCached() {\n            do {\n                let cacheFileUrl = URL(fileURLWithPath: Cache.supportPath.appending(\"/\" + name + \"/entries.json\"))\n                let jsondata = try Data(contentsOf: cacheFileUrl)\n\n                if name == \"tvOS 10\" {\n                    return parseOldVideoManifest(jsondata)\n                } else if name.starts(with: \"tvOS 13\") {\n                    return parseVideoManifest(jsondata) + getMissingVideos()  // Oh, Victoria Harbour 2...\n                } else if name.starts(with: \"macOS\") {\n                    return parseMacManifest(jsondata)\n                } else {\n                    return parseVideoManifest(jsondata)\n                }\n            } catch {\n                errorLog(\"\\(name) could not be opened\")\n                return []\n            }\n        } else {\n            debugLog(\"\\(name) is not cached\")\n            return []\n        }\n    }\n\n    func localizePath(_ path: String?) -> String {\n        if let tpath = path {\n            if manifestUrl.starts(with: \"file://\") {\n                return manifestUrl + tpath\n            }\n\n            return tpath\n        } else {\n            return \"\"\n        }\n    }\n\n    // The things we do for one single missing video (for now) ;)\n    func getMissingVideos() -> [AerialVideo] {\n        // We also need to add the missing videos\n        let bundlePath = Bundle(for: PanelWindowController.self).path(forResource: \"missingvideos\", ofType: \"json\")!\n        do {\n            let data = try Data(contentsOf: URL(fileURLWithPath: bundlePath), options: .mappedIfSafe)\n            return parseVideoManifest(data)\n        } catch {\n            errorLog(\"missingvideos.json was not found in the bundle\")\n        }\n\n        return []\n    }\n\n    // MARK: - JSON processing\n    func readOldJSONFromData(_ data: Data) -> [AerialVideo] {\n        var processedVideos: [AerialVideo] = []\n\n        do {\n            let poiStringProvider = PoiStringProvider.sharedInstance\n\n            let options = JSONSerialization.ReadingOptions.allowFragments\n            let batches = try JSONSerialization.jsonObject(with: data,\n                                                           options: options) as! [NSDictionary]\n\n            for batch: NSDictionary in batches {\n                let assets = batch[\"assets\"] as! [NSDictionary]\n                // rawCount = assets.count\n\n                for item in assets {\n                    let url = item[\"url\"] as! String\n                    let name = item[\"accessibilityLabel\"] as! String\n                    let timeOfDay = item[\"timeOfDay\"] as! String\n                    let id = item[\"id\"] as! String\n                    let type = item[\"type\"] as! String\n\n                    if type != \"video\" {\n                        continue\n                    }\n\n                    // We may have a secondary name\n                    var secondaryName = \"\"\n                    if let mergename = poiStringProvider.getCommunityName(id: id) {\n                        secondaryName = mergename\n                    }\n\n                    // We may have POIs to merge\n                    /*var poi: [String: String]?\n                    if let mergeId = SourceInfo.mergePOI[id] {\n                        let poiStringProvider = PoiStringProvider.sharedInstance\n                        poi = poiStringProvider.fetchExtraPoiForId(id: mergeId)\n                    }*/\n\n                    let communityPoi = poiStringProvider.getCommunityPoi(id: id)\n\n                    // We may have dupes...\n                    let (isDupe, foundDupe) = SourceInfo.findDuplicate(id: id, url1080pH264: url)\n                    if isDupe {\n                        if foundDupe != nil {\n                            // foundDupe!.sources.append(manifest)\n\n                            if foundDupe?.urls[.v1080pH264] == \"\" {\n                                foundDupe?.urls[.v1080pH264] = url\n                            }\n                        }\n                    } else {\n                        var url1080pHEVC = \"\"\n                        var url1080pHDR = \"\"\n                        var url4KHEVC = \"\"\n                        var url4KHDR = \"\"\n\n                        // Check if we have some HEVC urls to merge\n                        if let val = SourceInfo.mergeInfo[id] {\n                            url1080pHEVC = val[\"url-1080-SDR\"]!\n                            url1080pHDR = val[\"url-1080-HDR\"]!\n                            url4KHEVC = val[\"url-4K-SDR\"]!\n                            url4KHDR = val[\"url-4K-HDR\"]!\n                        }\n\n                        let urls: [VideoFormat: String] = [.v1080pH264: url,\n                                                           .v1080pHEVC: url1080pHEVC,\n                                                           .v1080pHDR: url1080pHDR,\n                                                           .v4KHEVC: url4KHEVC,\n                                                           .v4KHDR: url4KHDR ]\n\n                        // Now we can finally add...\n                        let video = AerialVideo(id: id,             // Must have\n                            name: name,         // Must have\n                            secondaryName: secondaryName,\n                            type: type,         // Not sure the point of this one ?\n                            timeOfDay: timeOfDay,\n                            scene: \"landscape\",\n                            urls: urls,\n                            source: self,\n                            poi: [:],\n                            communityPoi: communityPoi)\n\n                        processedVideos.append(video)\n                    }\n                }\n            }\n\n            return processedVideos\n        } catch {\n            errorLog(\"Error retrieving content listing (old)\")\n            return []\n        }\n    }\n    \n    func getSubcategoryFor(_ asset: MacAsset, manifest: MacManifest) -> String {\n        for category in manifest.categories {\n            if category.subcategories != nil {\n                for subcategory in category.subcategories! {\n                    if subcategory.id == asset.subcategories.first {\n                        return PoiStringProvider.sharedInstance.getLocalizedNameKey(key:subcategory.localizedNameKey)\n                    }\n                }\n            }\n        }\n        \n        return \"Not found\"\n    }\n\n    func getSecondaryNameFor(_ asset: VideoAsset) -> String {\n        let poiStringProvider = PoiStringProvider.sharedInstance\n\n        if let mergename = poiStringProvider.getCommunityName(id: asset.id) {\n            return mergename\n        } else {\n            return asset.title ?? \"Unknown\"\n        }\n    }\n\n    func getSecondaryNameFor(_ asset: MacAsset) -> String {\n        let poiStringProvider = PoiStringProvider.sharedInstance\n\n        return poiStringProvider.getLocalizedNameKey(key: asset.localizedNameKey)\n    }\n\n    \n    func getSceneFor(_ asset: VideoAsset) -> String {\n        if let updatedScene = SourceInfo.getSceneForVideo(id: asset.id) {\n            return updatedScene.rawValue.lowercased()\n        } else {\n            return asset.scene ?? \"landscape\"\n        }\n    }\n\n    func getSceneFor(_ asset: MacAsset) -> String {\n        if let updatedScene = SourceInfo.getSceneForVideo(id: asset.id) {\n            return updatedScene.rawValue.lowercased()\n        } else {\n            return \"landscape\"\n        }\n    }\n\n    \n    // Generate URLs\n    func urlsFor(_ asset: VideoAsset) -> [VideoFormat: String] {\n        return [.v1080pH264: localizePath(asset.url1080H264),\n                .v1080pHEVC: localizePath(asset.url1080SDR),\n                .v1080pHDR: localizePath(asset.url1080HDR),\n                .v4KHEVC: localizePath(asset.url4KSDR),\n                .v4KHDR: localizePath(asset.url4KHDR),\n                .v4KSDR240: localizePath(asset.url4KSDR240FPS) ]\n    }\n\n    // Mac manifest only has 240 fps\n    func urlsFor(_ asset: MacAsset) -> [VideoFormat: String] {\n        return [.v1080pH264: \"\",\n                .v1080pHEVC: \"\",\n                .v1080pHDR: \"\",\n                .v4KHEVC: \"\",\n                .v4KHDR: \"\",\n                .v4KSDR240: localizePath(asset.url4KSDR240FPS) ]\n    }\n    \n    func oldUrlsFor(_ asset: VideoAsset) -> [VideoFormat: String] {\n        var url1080pHEVC = \"\"\n        var url1080pHDR = \"\"\n        var url4KHEVC = \"\"\n        var url4KHDR = \"\"\n\n        // Check if we have some HEVC urls to merge\n        if let val = SourceInfo.mergeInfo[asset.id] {\n            url1080pHEVC = val[\"url-1080-SDR\"]!\n            url1080pHDR = val[\"url-1080-HDR\"]!\n            url4KHEVC = val[\"url-4K-SDR\"]!\n            url4KHDR = val[\"url-4K-HDR\"]!\n        }\n\n        return [.v1080pH264: asset.url ?? \"\",\n                .v1080pHEVC: url1080pHEVC,\n                .v1080pHDR: url1080pHDR,\n                .v4KHEVC: url4KHEVC,\n                .v4KHDR: url4KHDR ]\n    }\n\n    func parseOldVideoManifest(_ data: Data) -> [AerialVideo] {\n        do {\n            let oldVideoManifest = try newJSONDecoder().decode(OldVideoManifest.self, from: data)\n            var processedVideos: [AerialVideo] = []\n\n            for group in oldVideoManifest {\n                for asset in group.assets {\n                    let (isDupe, foundDupe) = SourceInfo.findDuplicate(id: asset.id, url1080pH264: asset.url ?? \"\")\n\n                    if isDupe {\n                        if let dupe = foundDupe {\n                            if dupe.urls[.v1080pH264] == \"\" {\n                                dupe.urls[.v1080pH264] = asset.url\n                            }\n                        }\n                    } else {\n                        var poi: [String: String]?\n                        if let mergeId = SourceInfo.mergePOI[asset.id] {\n                            let poiStringProvider = PoiStringProvider.sharedInstance\n                            poi = poiStringProvider.fetchExtraPoiForId(id: mergeId)\n                        }\n\n                        let video = AerialVideo(id: asset.id,\n                            name: asset.accessibilityLabel,\n                            secondaryName: getSecondaryNameFor(asset),\n                            type: \"video\",\n                            timeOfDay: asset.timeOfDay ?? \"day\",\n                            scene: getSceneFor(asset),\n                            urls: oldUrlsFor(asset),\n                            source: self,\n                            poi: poi ?? [:],\n                            communityPoi: PoiStringProvider.sharedInstance.getCommunityPoi(id: asset.id))\n\n                        processedVideos.append(video)\n                    }\n                }\n            }\n\n            return processedVideos\n        } catch let error {\n            debugLog(error.localizedDescription)\n            errorLog(\"### Could not parse manifest data\")\n            return []\n        }\n    }\n\n    func readVideoManifest(_ data: Data) -> [AerialVideo] {\n        if let videoManifest = try? newJSONDecoder().decode(VideoManifest.self, from: data) {\n            var processedVideos: [AerialVideo] = []\n\n            for asset in videoManifest.assets {\n                let video = AerialVideo(id: asset.id,\n                    name: asset.accessibilityLabel,\n                    secondaryName: getSecondaryNameFor(asset),\n                    type: \"video\",\n                    timeOfDay: asset.timeOfDay ?? \"day\",\n                    scene: getSceneFor(asset),\n                    urls: urlsFor(asset),\n                    source: self,\n                    poi: asset.pointsOfInterest ?? [:],\n                    communityPoi: PoiStringProvider.sharedInstance.getCommunityPoi(id: asset.id))\n\n                processedVideos.append(video)\n            }\n\n            return processedVideos\n        }\n\n        errorLog(\"### Could not parse manifest data\")\n        return []\n    }\n\n    func parseVideoManifest(_ data: Data) -> [AerialVideo] {\n        if let videoManifest = try? newJSONDecoder().decode(VideoManifest.self, from: data) {\n            var processedVideos: [AerialVideo] = []\n\n            for asset in videoManifest.assets {\n                let (isDupe, foundVideo) = SourceInfo.findDuplicate(id: asset.id, url1080pH264: asset.url1080H264 ?? \"\")\n\n                if !isDupe {\n                    let video = AerialVideo(id: asset.id,\n                        name: asset.accessibilityLabel,\n                        secondaryName: getSecondaryNameFor(asset),\n                        type: \"video\",\n                        timeOfDay: asset.timeOfDay ?? \"day\",\n                        scene: getSceneFor(asset),\n                        urls: urlsFor(asset),\n                        source: self,\n                        poi: asset.pointsOfInterest ?? [:],\n                        communityPoi: PoiStringProvider.sharedInstance.getCommunityPoi(id: asset.id))\n\n                    processedVideos.append(video)\n                } else {\n                    // Merge urls with macOS manifest\n                    let assetURLs = urlsFor(asset)\n                    if foundVideo?.urls[.v4KHDR] == \"\" {\n                        foundVideo?.urls[.v4KHDR] = assetURLs[.v4KHDR]\n                    }\n                    if foundVideo?.urls[.v4KHEVC] == \"\" {\n                        foundVideo?.urls[.v4KHEVC] = assetURLs[.v4KHEVC]\n                    }\n                    if foundVideo?.urls[.v1080pHDR] == \"\" {\n                        foundVideo?.urls[.v1080pHDR] = assetURLs[.v1080pHDR]\n                    }\n                    if foundVideo?.urls[.v1080pHEVC] == \"\" {\n                        foundVideo?.urls[.v1080pHEVC] = assetURLs[.v1080pHEVC]\n                    }\n                    if foundVideo?.urls[.v1080pH264] == \"\" {\n                        foundVideo?.urls[.v1080pH264] = assetURLs[.v1080pH264]\n                    }\n                }\n            }\n\n            return processedVideos\n        }\n\n        errorLog(\"### Could not parse manifest data\")\n        return []\n    }\n    \n    func parseMacManifest(_ data: Data) -> [AerialVideo] {\n        if let videoManifest = try? newJSONDecoder().decode(MacManifest.self, from: data) {\n            var processedVideos: [AerialVideo] = []\n\n            for asset in videoManifest.assets {\n                let (isDupe, _) = SourceInfo.findDuplicate(id: asset.id, url1080pH264: \"\")\n\n                if !isDupe {\n                    let video = AerialVideo(id: asset.id,\n                        name: getSubcategoryFor(asset, manifest: videoManifest),\n                        secondaryName: getSecondaryNameFor(asset),\n                        type: \"video\",\n                        timeOfDay: \"day\",\n                        scene: getSceneFor(asset),\n                        urls: urlsFor(asset),\n                        source: self,\n                        poi: asset.pointsOfInterest, // ?? [:],\n                        communityPoi: PoiStringProvider.sharedInstance.getCommunityPoi(id: asset.id))\n\n                    processedVideos.append(video)\n                }\n            }\n\n            return processedVideos\n        }\n\n        errorLog(\"### Could not parse manifest data\")\n        return []\n    }\n    \n}\n\n// MARK: - VideoManifest\n/// The newer format used by all our other JSONs\nstruct VideoManifest: Codable {\n    let assets: [VideoAsset]\n    let initialAssetCount, version: Int?\n}\n\n// MARK: - OldVideoManifestElement\n/// This is tvOS 10's manifest format\nstruct OldVideoManifestElement: Codable {\n    let id: String\n    let assets: [VideoAsset]\n}\n\ntypealias OldVideoManifest = [OldVideoManifestElement]\n\n// MARK: - VideoAsset\n/// Common Asset structure for all our JSONs\n///\n/// I've added multiple extra fields that aren't in Apple's JSONs, including:\n/// - title: as in Los Angeles (accesibilityLabel) / Santa Monica Beach (title)\n/// - timeOfDay: only on tvOS 10, resurected for custom sources, can also be sunset or sunrise\n/// - scene: landscape, city, space, sea\nstruct VideoAsset: Codable {\n    let accessibilityLabel, id: String\n    let title: String?\n    let timeOfDay: String?\n    let scene: String?\n    let pointsOfInterest: [String: String]?\n    let url4KHDR, url4KSDR, url1080H264, url1080HDR, url4KSDR120FPS, url4KSDR240FPS: String?\n    let url1080SDR, url: String?\n    let type: String?\n\n    enum CodingKeys: String, CodingKey {\n        case accessibilityLabel, id, pointsOfInterest\n        case title, timeOfDay, scene\n        case url4KHDR = \"url-4K-HDR\"\n        case url4KSDR = \"url-4K-SDR\"\n        case url1080H264 = \"url-1080-H264\"\n        case url1080HDR = \"url-1080-HDR\"\n        case url1080SDR = \"url-1080-SDR\"\n        case url4KSDR240FPS = \"url-4K-SDR-240FPS\"\n        case url4KSDR120FPS = \"url-4K-SDR-120FPS\"\n        case url\n        case type\n    }\n}\n\n// MARK: - MACManifest\nstruct MacManifest: Codable {\n    let localizationVersion: LocalizationVersion\n    let categories: [SubcategoryElement]\n    let initialAssetCount: Int\n    let assets: [MacAsset]\n    let version: Int\n}\n\n// MARK: - Asset\nstruct MacAsset: Codable {\n    let shotID: String\n    let previewImage: String\n    let previewImage900x580: String?\n    let localizedNameKey, accessibilityLabel: String\n    let preferredOrder: Int\n    let categories: [String]\n    let id: String\n    let subcategories: [String]\n    let pointsOfInterest: [String: String]\n    let url4KSDR240FPS: String\n    let includeInShuffle, showInTopLevel: Bool\n    let group: LocalizationVersion?\n\n    enum CodingKeys: String, CodingKey {\n        case shotID, previewImage, localizedNameKey, accessibilityLabel, preferredOrder, categories, id, subcategories, pointsOfInterest\n        case previewImage900x580 = \"previewImage-900x580\"\n        case url4KSDR240FPS = \"url-4K-SDR-240FPS\"\n        case includeInShuffle, showInTopLevel, group\n    }\n}\n\n\nenum LocalizationVersion: String, Codable {\n    case the19J1 = \"19J-1\"\n    case the19K1 = \"19K-1\"\n    case the21J1 = \"21J-1\"\n    case the22L1 = \"22L-1\"\n}\n\n// MARK: - SubcategoryElement\nstruct SubcategoryElement: Codable {\n    let subcategories: [SubcategoryElement]?\n    let localizedDescriptionKey, representativeAssetID: String\n    let previewImage: String\n    let id: String\n    let preferredOrder: Int\n    let localizedNameKey: String\n}\n"
  },
  {
    "path": "Aerial/Source/Models/Sources/SourceInfo.swift",
    "content": "//\n//  SourceInfo.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 08/07/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Foundation\n\n// swiftlint:disable:next type_body_length\nstruct SourceInfo {\n    // Those videos will be ignored\n    static let blacklist = [\"b10-1.mov\",           // Dupe of b1-1 (Hawaii, day)\n                     \"b10-2.mov\",           // Dupe of b2-3 (New York, night)\n                     \"b10-4.mov\",           // Dupe of b2-4 (San Francisco, night)\n                     \"b9-1.mov\",            // Dupe of b2-2 (Hawaii, day)\n                     \"b9-2.mov\",            // Dupe of b3-1 (London, night)\n                     \"comp_LA_A005_C009_v05_t9_6M.mov\",     // Low quality version of Los Angeles day 687B36CB-BA5D-4434-BA99-2F2B8B6EC163\n                     \"comp_LA_A009_C009_t9_6M_tag0.mov\"\n                     ]    // Low quality version of Los Angeles night 89B1643B-06DD-4DEC-B1B0-774493B0F7B7\n\n    // This is used for videos where URLs should be merged with different ID\n    // This is used to dedupe old versions of videos\n    // old : new\n    static let dupePairs = [\n        \"A2BE2E4A-AD4B-428A-9C41-BDAE1E78E816\": \"12318CCB-3F78-43B7-A854-EFDCCE5312CD\",     // California to Vegas (v7 -> v8)\n        \"6A74D52E-2447-4B84-AE45-0DEF2836C3CC\": \"7825C73A-658F-48EE-B14C-EC56673094AC\",     // China\n        \"7825C73A-658F-48EE-B14C-EC56673094AC\": \"6324F6EB-E0F1-468F-AC2E-A983EBDDD53B\",     // China again\n        \"6C3D54AE-0871-498A-81D0-56ED24E5FE9F\": \"009BA758-7060-4479-8EE8-FB9B40C8FB97\",     // Korean and Japan night\n        \"b5-1\": \"044AD56C-A107-41B2-90CC-E60CCACFBCF5\",                                     // Great Wall 3\n        \"b2-1\": \"22162A9B-DB90-4517-867C-C676BC3E8E95\",                                     // Great wall 2\n        \"b6-1\": \"F0236EC5-EE72-4058-A6CE-1F7D2E8253BF\",                                     // Great wall 1\n        \"BAF76353-3475-4855-B7E1-CE96CC9BC3A7\": \"9680B8EB-CE2A-4395-AF41-402801F4D6A6\",     // Approaching Burj Khalifa (night)\n        \"B3BDC635-756D-4B82-B01A-A2620D1DBF10\": \"9680B8EB-CE2A-4395-AF41-402801F4D6A6\",     // Approaching Burj Khalifa (night)\n        \"15F9B681-9EA8-4DD1-AD26-F111BC5CF64B\": \"E991AC0C-F272-44D8-88F3-05F44EDFE3AE\",     // Marina 1\n        \"49790B7C-7D8C-466C-A09E-83E38B6BE87A\": \"E991AC0C-F272-44D8-88F3-05F44EDFE3AE\",     // Marina 1\n        \"802866E6-4AAF-4A69-96EA-C582651391F1\": \"3FFA2A97-7D28-49EA-AA39-5BC9051B2745\",     // Marina 2\n        \"D34A7B19-EC33-4300-B4ED-0C8BC494C035\": \"3FFA2A97-7D28-49EA-AA39-5BC9051B2745\",     // Marina 2\n        \"02EA5DBE-3A67-4DFA-8528-12901DFD6CC1\": \"00BA71CD-2C54-415A-A68A-8358E677D750\",     // Downtown\n        \"AC9C09DD-1D97-4013-A09F-B0F5259E64C3\": \"876D51F4-3D78-4221-8AD2-F9E78C0FD9B9\",     // Sheikh Zayed Road (day)\n        \"DFA399FA-620A-4517-94D6-BF78BF8C5E5A\": \"876D51F4-3D78-4221-8AD2-F9E78C0FD9B9\",     // Sheikh Zayed Road (day)\n        \"D388F00A-5A32-4431-A95C-38BF7FF7268D\": \"B8F204CE-6024-49AB-85F9-7CA2F6DCD226\",     // Nuusuaq Peninsula\n        \"E4ED0B22-EB81-4D4F-A29E-7E1EA6B6D980\": \"B8F204CE-6024-49AB-85F9-7CA2F6DCD226\",     // Nuusuaq Peninsula\n        \"30047FDA-3AE3-4E74-9575-3520AD77865B\": \"2F52E34C-39D4-4AB1-9025-8F7141FAA720\",     // Ilulissat Icefjord day\n        \"7D4710EB-5BA4-42E6-AA60-68D77F67D9B9\": \"EE01F02D-1413-436C-AB05-410F224A5B7B\",     // Ilulissat Icefjord Night\n        \"b8-1\": \"82BD33C9-B6D2-47E7-9C42-AA3B7758921A\",                                     // Pu'u O 'Umi Night\n        \"b4-1\": \"258A6797-CC13-4C3A-AB35-4F25CA3BF474\",                                     // Pu'u O 'Umi day\n        \"b1-1\": \"12E0343D-2CD9-48EA-AB57-4D680FB6D0C7\",                                     // Waimanu Valley\n        \"b7-1\": \"499995FA-E51A-4ACE-8DFD-BDF8AFF6C943\",                                     // Laupāhoehoe Nui\n        \"b6-2\": \"3D729CFC-9000-48D3-A052-C5BD5B7A6842\",                                     // Kohala coastline\n        \"30313BC1-BF20-45EB-A7B1-5A6FFDBD2488\": \"E99FA658-A59A-4A2D-9F3B-58E7BDC71A9A\",     // Hong Kong Victoria Harbour night\n        \"2A57BB93-1825-484C-9609-FF8580CAE77B\": \"E99FA658-A59A-4A2D-9F3B-58E7BDC71A9A\",     // Hong Kong Victoria Harbour night\n        \"102C19D1-9D9F-48EC-B492-074C985C4D9F\": \"FE8E1F9D-59BA-4207-B626-28E34D810D0A\",     // Hong Kong Victoria Harbour 1\n        \"786E674C-BB22-4AA9-9BD3-114D2020EC4D\": \"64EA30BD-C4B5-4CDD-86D7-DFE47E9CB9AA\",     // Hong Kong Victoria Harbour 2\n        \"560E09E8-E89D-4ADB-8EEA-4754415383D4\": \"C8559883-6F3E-4AF2-8960-903710CD47B7\",     // Hong Kong Victoria Peak\n        \"6E2FC8AC-832D-46CF-B306-BB2A05030C17\": \"001C94AE-2BA4-4E77-A202-F7DE60E8B1C8\",     // Liwa oasis 1\n        \"88025454-6D58-48E8-A2DB-924988FAD7AC\": \"001C94AE-2BA4-4E77-A202-F7DE60E8B1C8\",     // Liwa oasis 1\n        \"b6-3\": \"58754319-8709-4AB0-8674-B34F04E7FFE2\",                                     // River Thames\n        \"b1-2\": \"F604AF56-EA77-4960-AEF7-82533CC1A8B3\",                                     // River Thames near sunset\n        \"b3-1\": \"7F4C26C2-67C2-4C3A-8F07-8A7BF6148C97\",                                     // River Times at Dusk\n        \"b5-2\": \"A5AAFF5D-8887-42BB-8AFD-867EF557ED85\",                                     // Buckingham Palace\n        \"BEED64EC-2DB7-47E1-A67E-59C101E73C04\": \"CE279831-1CA7-4A83-A97B-FF1E20234396\",     // LAX\n        \"829E69BA-BB53-4841-A138-4DF0C2A74236\": \"CE279831-1CA7-4A83-A97B-FF1E20234396\",     // LAX\n        \"60CD8E2E-35CD-4192-A5A4-D5E10BFE158B\": \"92E48DE9-13A1-4172-B560-29B4668A87EE\",     // Santa Monica Beach\n        \"B730433D-1B3B-4B99-9500-A286BF7A9940\": \"92E48DE9-13A1-4172-B560-29B4668A87EE\",     // Santa Monica Beach\n        \"30A2A488-E708-42E7-9A90-B749A407AE1C\": \"35693AEA-F8C4-4A80-B77D-C94B20A68956\",     // Harbor Freeway\n        \"A284F0BF-E690-4C13-92E2-4672D93E8DE5\": \"F5804DD6-5963-40DA-9FA0-39C0C6E6DEF9\",     // Downtown\n        \"b3-2\": \"840FE8E4-D952-4680-B1A7-AC5BACA2C1F8\",                                     // Upper East side\n        \"b4-2\": \"640DFB00-FBB9-45DA-9444-9F663859F4BC\",                                     // Lower Manhattan (night)\n        \"b2-3\": \"44166C39-8566-4ECA-BD16-43159429B52F\",                                     // Seventh Avenue\n        \"b7-2\": \"3BA0CFC7-E460-4B59-A817-B97F9EBB9B89\",                                     // Central Park\n        \"b10-3\": \"EE533FBD-90AE-419A-AD13-D7A60E2015D6\",                                    // Marin Headlands in Fog\n        \"b1-4\": \"3E94AE98-EAF2-4B09-96E3-452F46BC114E\",                                     // Bay bridge night\n        \"b9-3\": \"DE851E6D-C2BE-4D9F-AB54-0F9CE994DC51\",                                     // Bay and Golden Bridge\n        \"b7-3\": \"29BDF297-EB43-403A-8719-A78DA11A2948\",                                     // Fisherman's Wharf\n        \"b3-3\": \"85CE77BF-3413-4A7B-9B0F-732E96229A73\",                                     // Embarcadero, Market Street\n        \"391BDF6E-3279-4CE1-9CA5-0F82811452D7\": \"83C65C90-270C-4490-9C69-F51FE03D7F06\"  // Seals tvOS 15 is reusing an old id\n    ]\n\n    // Extra info to be merged for a given ID, as of right now only one known video\n    static let mergeInfo = [\n        \"2F11E857-4F77-4476-8033-4A1E4610AFCC\":\n            [\"url-1080-SDR\": \"https://sylvan.apple.com/Aerials/2x/Videos/DB_D011_C009_2K_SDR_HEVC.mov\",\n             \"url-1080-HDR\": \"https://sylvan.apple.com/Aerials/2x/Videos/DB_D011_C009_2K_HDR_HEVC.mov\",\n             \"url-4K-SDR\": \"https://sylvan.apple.com/Aerials/2x/Videos/DB_D011_C009_4K_SDR_HEVC.mov\",\n             \"url-4K-HDR\": \"https://sylvan.apple.com/Aerials/2x/Videos/DB_D011_C009_4K_HDR_HEVC.mov\" ]    // Dubai night 2\n    ]\n\n    static let cityVideos = [\n        \"b8-3\", // San Francisco - Alamo Square\n        \"9680B8EB-CE2A-4395-AF41-402801F4D6A6\", // Dubai - Approaching Burj Khalifa\n        \"3E94AE98-EAF2-4B09-96E3-452F46BC114E\", // San Francisco - Bay Bridge\n        \"4AD99907-9E76-408D-A7FC-8429FF014201\", // San Francisco - Bay and Embarcadero\n        \"A5AAFF5D-8887-42BB-8AFD-867EF557ED85\", // London - Buckingham Palace\n        \"3BA0CFC7-E460-4B59-A817-B97F9EBB9B89\", // New York - Central Park\n        \"00BA71CD-2C54-415A-A68A-8358E677D750\", // Dubai - Downtown\n        \"F5804DD6-5963-40DA-9FA0-39C0C6E6DEF9\", // Los Angeles - Downtown\n        \"b6-4\", // San Francisco - Downtown and Coit Tower\n        \"b2-4\", // San Francisco - Downtown and Sutro Tower\n        \"85CE77BF-3413-4A7B-9B0F-732E96229A73\", // San Francisco - Embarcadero, Market Street\n        \"b5-3\", // San Francisco - Embarcadero, Market Street\n        \"29BDF297-EB43-403A-8719-A78DA11A2948\", // San Francisco - Fisherman’s Wharf\n        \"35693AEA-F8C4-4A80-B77D-C94B20A68956\", // Los Angeles - Harbor Freeway\n        \"CE279831-1CA7-4A83-A97B-FF1E20234396\", // Los Angeles - Los Angeles Int’l Airport\n        \"640DFB00-FBB9-45DA-9444-9F663859F4BC\", // New York - Lower Manhattan\n        \"b1-3\", // New York - Lower Manhattan\n        \"E991AC0C-F272-44D8-88F3-05F44EDFE3AE\", // Dubai - Marina 1\n        \"3FFA2A97-7D28-49EA-AA39-5BC9051B2745\", // Dubai - Marina 2\n        \"58754319-8709-4AB0-8674-B34F04E7FFE2\", // London - River Thames\n        \"7F4C26C2-67C2-4C3A-8F07-8A7BF6148C97\", // London - River Thames at Dusk\n        \"F604AF56-EA77-4960-AEF7-82533CC1A8B3\", // London - River Thames near Sunset\n        \"44166C39-8566-4ECA-BD16-43159429B52F\", // New York - Seventh Avenue\n        \"876D51F4-3D78-4221-8AD2-F9E78C0FD9B9\", // Dubai - Sheikh Zayed Road\n        \"2F11E857-4F77-4476-8033-4A1E4610AFCC\", // Dubai - Sheikh Zayed Road\n        \"840FE8E4-D952-4680-B1A7-AC5BACA2C1F8\", // New York - Upper East Side\n        \"E99FA658-A59A-4A2D-9F3B-58E7BDC71A9A\", // Hong Kong - Victoria Harbour\n        \"FE8E1F9D-59BA-4207-B626-28E34D810D0A\", // Hong Kong - Victoria Harbour 1\n        \"64EA30BD-C4B5-4CDD-86D7-DFE47E9CB9AA\", // Hong Kong - Victoria Harbour 2\n        \"C8559883-6F3E-4AF2-8960-903710CD47B7\", // Hong Kong - Victoria Peak\n        \"024891DE-B7F6-4187-BFE0-E6D237702EF0\" // Hong Kong - Wan Chai\n    ]\n\n    static let countrySideVideos = [\n        \"DE851E6D-C2BE-4D9F-AB54-0F9CE994DC51\", // San Francisco - Bay and Golden Gate\n        \"72B4390D-DF1D-4D51-B179-229BBAEFFF2C\", // San Francisco - Golden Gate from SF\n        \"b8-2\", // San Francisco - Marin Headlands\n        \"EE533FBD-90AE-419A-AD13-D7A60E2015D6\", // San Francisco - Marin Headlands in Fog\n        \"89B1643B-06DD-4DEC-B1B0-774493B0F7B7\", // Los Angeles - Griffith Observatory\n        \"EC67726A-8212-4C5E-83CF-8412932740D2\", // Los Angeles - Hollywood Hills\n        \"b4-3\" // San Francisco - Presidio to Golden Gate\n    ]\n\n    static let beachVideos = [\n        \"b2-2\", // Hawaii - Honopū Valley\n        \"3D729CFC-9000-48D3-A052-C5BD5B7A6842\", // Hawaii - Kohala Coastline\n        \"12E0343D-2CD9-48EA-AB57-4D680FB6D0C7\", // Hawaii - Laupāhoehoe Nui\n        \"92E48DE9-13A1-4172-B560-29B4668A87EE\" // Los Angeles - Santa Monica Beach\n    ]\n\n    static let spaceVideos = [\n        \"A837FA8C-C643-4705-AE92-074EFDD067F7\",\n        \"2F72BC1E-3D76-456C-81EB-842EBA488C27\",\n        \"A2BE2E4A-AD4B-428A-9C41-BDAE1E78E816\",\n        \"12318CCB-3F78-43B7-A854-EFDCCE5312CD\",\n        \"D5CFB2FF-5F8C-4637-816B-3E42FC1229B8\",\n        \"4F881F8B-A7D9-4FDB-A917-17BF6AC5A589\",\n        \"6A74D52E-2447-4B84-AE45-0DEF2836C3CC\",\n        \"7825C73A-658F-48EE-B14C-EC56673094AC\",\n        \"E5DB138A-F04E-4619-B896-DE5CB538C534\",\n        \"F439B0A7-D18C-4B14-9681-6520E6A74FE9\",\n        \"62A926BE-AA0B-4A34-9653-78C4F130543F\",\n        \"7C643A39-C0B2-4BA0-8BC2-2EAA47CC580E\",\n        \"6C3D54AE-0871-498A-81D0-56ED24E5FE9F\",\n        \"009BA758-7060-4479-8EE8-FB9B40C8FB97\",\n        \"78911B7E-3C69-47AD-B635-9C2486F6301D\",\n        \"D60B4DDA-69EB-4841-9690-E8BAE7BC4F80\",\n        \"7719B48A-2005-4011-9280-2F64EEC6FD91\",\n        \"63C042F0-90EF-4A95-B7CC-CC9A64BF8421\",\n        \"B1B5DDC5-73C8-4920-8133-BACCE38A08DE\",\n        \"03EC0F5E-CCA8-4E0A-9FEC-5BD1CE151182\",             // 25/01 Antartica Aurora\n        \"737E9E24-49BE-4104-9B72-F352DE1AD2BF\",             // North America Aurora\n        \"E556BBC5-D0A0-4DB1-AC77-BC76E4A526F4\",             // Sahara and Italy\n        \"64D11DAB-3B57-4F14-AD2F-E59A9282FA44\",             // Atlantic Ocean to Spain and France\n        \"81337355-E156-4242-AAF4-711768D30A54\",             // Australia\n        \"1088217C-1410-4CF7-BDE9-8F573A4DBCD9\",             // Caribbean\n        \"3C4678E4-4D3D-4A40-8817-77752AEA62EB\",             // Nile Delta\n        \"87060EC2-D006-4102-98CC-3005C68BB343\"             // South Africa to North Asia\n\n    ]\n\n    static let seaVideos = [\n        \"83C65C90-270C-4490-9C69-F51FE03D7F06\", // Seals (outdated)\n        \"BA4ECA11-592F-4727-9221-D2A32A16EB28\", // Palau Jellies *\n        \"F07CC61B-30FC-4614-BDAD-3240B61F6793\", // Palau Coral\n        \"6143116D-03BB-485E-864E-A8CF58ACF6F1\", // Kelp\n        \"2B30E324-E4FF-4CC1-BA45-A958C2D2B2EC\", // Barracuda\n        \"E580E5A5-0888-4BE8-A4CA-F74A18A643C3\", // Palau Jellies *\n        \"EC3DC957-D4C2-4732-AACE-7D0C0F390EC8\", // Palau Jellies *\n        \"581A4F1A-2B6D-468C-A1BE-6F473F06D10B\", // Sea Stars\n        \"687D03A2-18A5-4181-8E85-38F3A13409B9\", // Bumpheads\n        \"537A4DAB-83B0-4B66-BCD1-05E5DBB4A268\", // Jacks\n        \"C7AD3D0A-7EDF-412C-A237-B3C9D27381A1\", // Alaskan Jellies *\n        \"C6DC4E54-1130-44F8-AF6F-A551D8E8A181\", // Alaskan Jellies *\n        \"27A37B0F-738D-4644-A7A4-E33E7A6C1175\", // California Dolphins\n        \"EB3F48E7-D30F-4079-858F-1A61331D5026\", // California Kelp Forest\n        \"CE9B5D5B-B6E7-47C5-8C04-59BF182E98FB\", // Costa Rica Dolphins\n        \"58C75C62-3290-47B8-849C-56A583173570\", // Cownose Rays\n        \"3716DD4B-01C0-4F5B-8DD6-DB771EC472FB\", // Gray Reef Sharks\n        \"DD47D8E1-CB66-4C12-BFEA-2ADB0D8D1E2E\", // Humpback Whale\n        \"82175C1F-153C-4EC8-AE37-2860EA828004\", // Red Sea Coral\n        \"149E7795-DBDA-4F5D-B39A-14712F841118\", // Tahiti Waves *\n        \"8C31B06F-91A4-4F7C-93ED-56146D7F48B9\", // Tahiti Waves *\n        \"391BDF6E-3279-4CE1-9CA5-0F82811452D7\" // Seals (new version)\n    ]\n\n    static let timeInformation = [\n        \"A837FA8C-C643-4705-AE92-074EFDD067F7\": \"night\",    // Africa Night\n        \"03EC0F5E-CCA8-4E0A-9FEC-5BD1CE151182\": \"sunrise\", // Space - Antartica\n        \"64D11DAB-3B57-4F14-AD2F-E59A9282FA44\": \"sunset\", // Space - Atlantic Ocean to Spain and France\n        \"81337355-E156-4242-AAF4-711768D30A54\": \"night\", // Space - Australia\n        \"A2BE2E4A-AD4B-428A-9C41-BDAE1E78E816\": \"night\",    // California to Vegas (v7)\n        \"12318CCB-3F78-43B7-A854-EFDCCE5312CD\": \"night\",    // California to Vegas (v8)\n        \"6A74D52E-2447-4B84-AE45-0DEF2836C3CC\": \"night\",    // China\n        \"7825C73A-658F-48EE-B14C-EC56673094AC\": \"night\",    // China (new id)\n\n        \"E5DB138A-F04E-4619-B896-DE5CB538C534\": \"night\",    // Italy to Asia\n        \"F439B0A7-D18C-4B14-9681-6520E6A74FE9\": \"sunset\",    // Iran and Afghanistan\n        \"62A926BE-AA0B-4A34-9653-78C4F130543F\": \"night\",    // Ireland to Asia\n        \"7C643A39-C0B2-4BA0-8BC2-2EAA47CC580E\": \"night\",    // Ireland to Asia\n        \"6C3D54AE-0871-498A-81D0-56ED24E5FE9F\": \"night\",    // Korean and Japan Night (v17)\n        \"009BA758-7060-4479-8EE8-FB9B40C8FB97\": \"night\",    // Korean and Japan Night (v18)\n        \"B1B5DDC5-73C8-4920-8133-BACCE38A08DE\": \"night\", // Space - Mexico City to New York\n        \"78911B7E-3C69-47AD-B635-9C2486F6301D\": \"sunrise\", // Space - New Zealand\n        \"737E9E24-49BE-4104-9B72-F352DE1AD2BF\": \"sunrise\", // Space - North America Aurora\n        \"87060EC2-D006-4102-98CC-3005C68BB343\": \"sunset\", // Space - South Africa to North Asia\n        \"63C042F0-90EF-4A95-B7CC-CC9A64BF8421\": \"sunset\", // Space - West Africa to the Alps\n\n        \"044AD56C-A107-41B2-90CC-E60CCACFBCF5\": \"sunset\", // China - Great Wall 3\n        \"EE01F02D-1413-436C-AB05-410F224A5B7B\": \"sunset\", // Greenland - Ilulissat Icefjord\n        \"B8F204CE-6024-49AB-85F9-7CA2F6DCD226\": \"sunrise\", // Greenland - Nuussuaq Peninsula\n        \"82BD33C9-B6D2-47E7-9C42-AA3B7758921A\": \"sunset\", // Hawaii - Pu‘u O ‘Umi\n\n        \"9680B8EB-CE2A-4395-AF41-402801F4D6A6\": \"night\",    // Approaching Burj Khalifa\n        \"3E94AE98-EAF2-4B09-96E3-452F46BC114E\": \"night\", // San Francisco - Bay Bridge\n        \"4AD99907-9E76-408D-A7FC-8429FF014201\": \"sunset\", // San Francisco - Bay and Embarcadero\n        \"00BA71CD-2C54-415A-A68A-8358E677D750\": \"sunrise\", // Dubai - Downtown\n        \"F5804DD6-5963-40DA-9FA0-39C0C6E6DEF9\": \"night\", // Los Angeles - Downtown\n\n        \"b6-4\": \"sunset\", // San Francisco - Downtown and Coit Tower\n        \"b2-4\": \"sunset\", // San Francisco - Downtown and Sutro Tower\n        \"85CE77BF-3413-4A7B-9B0F-732E96229A73\": \"sunrise\", // San Francisco - Embarcadero, Market Street\n        \"b5-3\": \"sunset\", // San Francisco - Embarcadero, Market Street\n        \"29BDF297-EB43-403A-8719-A78DA11A2948\": \"sunrise\", // San Francisco - Fisherman’s Wharf\n        \"640DFB00-FBB9-45DA-9444-9F663859F4BC\": \"sunset\", // New York - Lower Manhattan\n        \"7F4C26C2-67C2-4C3A-8F07-8A7BF6148C97\": \"sunset\", // London - River Thames at Dusk\n        \"F604AF56-EA77-4960-AEF7-82533CC1A8B3\": \"sunset\", // London - River Thames near Sunset\n        \"44166C39-8566-4ECA-BD16-43159429B52F\": \"night\", // New York - Seventh Avenue\n        \"2F11E857-4F77-4476-8033-4A1E4610AFCC\": \"night\", // Dubai - Sheikh Zayed Road\n        \"E99FA658-A59A-4A2D-9F3B-58E7BDC71A9A\": \"sunset\", // Hong Kong - Victoria Harbour\n\n        \"3D729CFC-9000-48D3-A052-C5BD5B7A6842\": \"sunset\", // Hawaii - Kohala Coastline\n\n        \"89B1643B-06DD-4DEC-B1B0-774493B0F7B7\": \"sunset\", // Los Angeles - Griffith Observatory\n        \"EC67726A-8212-4C5E-83CF-8412932740D2\": \"sunset\", // Los Angeles - Hollywood Hills\n        \"EE533FBD-90AE-419A-AD13-D7A60E2015D6\": \"sunrise\", // San Francisco - Marin Headlands in Fog\n        \"b4-3\": \"sunrise\" // San Francisco - Presidio to Golden Gate\n\n        // \"BAF76353-3475-4855-B7E1-CE96CC9BC3A7\": \"night\",    // Dubai\n        // \"30313BC1-BF20-45EB-A7B1-5A6FFDBD2488\": \"night\",    // Hong Kong\n        // \"A284F0BF-E690-4C13-92E2-4672D93E8DE5\": \"night\",    // Los Angeles (old ?)\n\n        // \"44166C39-8566-4ECA-BD16-43159429B52F\": \"night\",    // Seventh Avenue\n    ]\n\n    // Extra POI\n    static let mergePOI = [\n            \"b6-1\": \"C001_C005_\",    // China day 4\n            \"b2-1\": \"C004_C003_\",    // China day 5\n            \"b5-1\": \"C003_C003_\",    // China day 6\n            \"7D4710EB-5BA4-42E6-AA60-68D77F67D9B9\": \"GL_G010_C006_\",             // Greenland night 1\n            \"b7-1\": \"H007_C003\",                                                 // Hawaii day 1\n            \"b1-1\": \"H005_C012_\",                                                // Hawaii day 2\n            \"b2-2\": \"H010_C006_\",                                                // Hawaii day 3\n            \"b4-1\": \"H004_C007_\",                                                // Hawaii day 4\n            \"b6-2\": \"H012_C009_\",                                                // Hawaii night 1\n            \"b8-1\": \"H004_C009_\",                                                // Hawaii night 2\n            \"6E2FC8AC-832D-46CF-B306-BB2A05030C17\": \"LW_L001_C006_\",             // Liwa day 1 LW_L001_C006_0\n            \"b6-3\": \"L010_C006_\",                                                // London day 1\n            \"b5-2\": \"L007_C007_\",                                                // London day 2\n            \"b1-2\": \"L012_C002_\",                                                // London night 1\n            \"b3-1\": \"L004_C011_\",                                                // London night 2\n            \"A284F0BF-E690-4C13-92E2-4672D93E8DE5\": \"LA_A011_C003_\",             // Los Angeles night 3\n            \"b7-2\": \"N008_C009_\",                                                // New York day 1\n            \"b1-3\": \"N006_C003_\",                                                // New York day 2\n            \"b3-2\": \"N003_C006_\",                                                // New York day 3\n            \"b2-3\": \"N013_C004_\",                                                // New York night 1\n            \"b4-2\": \"N008_C003_\",                                                // New York night 2\n            \"b8-2\": \"A008_C007_\",                                                // San Francisco day 1\n            // \"b10-3\": ,                                               // San Francisco day 2\n            \"b9-3\": \"A006_C003_\",                                                // San Francisco day 3\n            // \"b8-3\":\"\",     San Francisco day 4 (no extra poi ?)\n            \"b3-3\": \"A012_C014_\",                                                // San Francisco day 5\n                                                                                //   maybe A013_C004 ?\n            \"b4-3\": \"A013_C005_\",                                                // San Francisco day 6\n            \"b6-4\": \"A004_C012_\",                                                // San Francisco night 1\n            \"b7-3\": \"A007_C017_\",                                                // San Francisco night 2\n            \"b5-3\": \"A015_C014_\",                                                // San Francisco night 3\n            \"b1-4\": \"A015_C018_\",                                                // San Francisco night 4\n            \"b2-4\": \"A018_C014_\",                                                 // San Francisco night 5\n            \"2F11E857-4F77-4476-8033-4A1E4610AFCC\": \"DB_D008_C010_\"        // Stealing the day description for the night one\n\n        ]\n    // Look for a previously processed similar video\n    //\n    // tvOS11 and 12 JSON are using the same ID (and tvOS12 JSON always has better data,\n    // so no need for a fancy merge)\n    //\n    // tvOS10 however JSON DOES NOT use the same ID, so we need to dupecheck on the h264\n    // (only available format there) filename (they actually have different URLs !)\n    static func findDuplicate(id: String, url1080pH264: String) -> (Bool, AerialVideo?) {\n        // We blacklist some duplicates\n        if url1080pH264 != \"\" {\n            if blacklist.contains((URL(string: url1080pH264)?.lastPathComponent)!) {\n                return (true, nil)\n            }\n        }\n\n        // We also have a Dictionary of duplicates that need source merging\n        for (pid, replace) in dupePairs where id == pid {\n            for vid in VideoList.instance.videos where vid.id == replace {\n                // Found dupe pair\n                return (true, vid)\n            }\n        }\n\n        for video in VideoList.instance.videos {\n            if id == video.id {\n                return (true, video)\n            } else if url1080pH264 != \"\" && video.urls[.v1080pH264] != \"\" {\n                if URL(string: url1080pH264)?.lastPathComponent == URL(string: video.urls[.v1080pH264]!)?.lastPathComponent {\n                    return (true, video)\n                }\n            }\n        }\n\n        return (false, nil)\n    }\n\n    static func getSceneForVideo(id: String) -> SourceScene? {\n        if seaVideos.contains(id) {\n            return .sea\n        } else if spaceVideos.contains(id) {\n            return .space\n        } else if cityVideos.contains(id) {\n            return .city\n        } else if countrySideVideos.contains(id) {\n            return .countryside\n        } else if beachVideos.contains(id) {\n            return .beach\n        }\n\n        return nil\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Models/Sources/SourceList.swift",
    "content": "//\n//  SourceList.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 01/07/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Foundation\n\nstruct SourceHeader {\n    let name: String\n    let sources: [Source]\n}\n\n// swiftlint:disable:next type_body_length\nstruct SourceList {\n    // This is the current one until next fall\n    /*static let macOS15 = Source(name: \"macOS 15\",\n                        description: \"High framerate videos from macOS 15 Sequoia\",\n                        manifestUrl: \"https://sylvan.apple.com/itunes-assets/Aerials126/v4/82/2e/34/822e344c-f5d2-878c-3d56-508d5b09ed61/resources-15-0-2.tar\",\n                        type: .macOS,\n                        scenes: [.nature, .city, .space, .sea],\n                        isCachable: true,\n                        license: \"\",\n                        more: \"\")*/\n    \n    static let macOS26 = Source(name: \"macOS 26\",\n                        description: \"High framerate videos from macOS 26\",\n                        manifestUrl: \"https://sylvan.apple.com/itunes-assets/Aerials126/v4/82/2e/34/822e344c-f5d2-878c-3d56-508d5b09ed61/resources-26-0-1.tar\",\n                        type: .macOS,\n                        scenes: [.nature, .city, .space, .sea],\n                        isCachable: true,\n                        license: \"\",\n                        more: \"\")\n    \n    // This is the current one until next fall\n    /*static let macOS14 = Source(name: \"macOS 14\",\n                        description: \"High framerate videos from macOS 14 Sonoma\",\n                        manifestUrl: \"https://sylvan.apple.com/itunes-assets/Aerials126/v4/82/2e/34/822e344c-f5d2-878c-3d56-508d5b09ed61/resources-14-0-10.tar\",\n                        type: .macOS,\n                        scenes: [.nature, .city, .space, .sea],\n                        isCachable: true,\n                        license: \"\",\n                        more: \"\")*/\n\n    // This is the current one until next fall\n    static let tvOS16 = Source(name: \"tvOS 16\",\n                        description: \"Apple TV screensavers from tvOS 16\",\n                        manifestUrl: \"https://sylvan.apple.com/Aerials/resources-16.tar\",\n                        type: .tvOS12,\n                        scenes: [.nature, .city, .space, .sea],\n                        isCachable: true,\n                        license: \"\",\n                        more: \"\")\n\n    // Legacy sources\n    static let tvOS13 = Source(name: \"tvOS 13\",\n                        description: \"Apple TV screensavers from tvOS 13\",\n                        manifestUrl: \"https://sylvan.apple.com/Aerials/resources-13.tar\",\n                        type: .tvOS12,\n                        scenes: [.nature, .city, .space, .sea],\n                        isCachable: true,\n                        license: \"\",\n                        more: \"\")\n\n    /*static let tvOS12 = Source(name: \"tvOS 12\",\n                        description: \"Apple TV screensavers from tvOS 12\",\n                        manifestUrl: \"https://sylvan.apple.com/Aerials/resources.tar\",\n                        type: .tvOS12,\n                        scenes: [.nature, .city, .space],\n                        isCachable: true,\n                        license: \"\",\n                        more: \"\")\n\n    static let tvOS11 = Source(name: \"tvOS 11\",\n                        description: \"Apple TV screensavers from tvOS 11\",\n                        manifestUrl: \"https://sylvan.apple.com/Aerials/2x/entries.json\",\n                        type: .tvOS11,\n                        scenes: [.nature, .city],\n                        isCachable: true,\n                        license: \"\",\n                        more: \"\")*/\n\n   /* static let tvOS10 = Source(name: \"tvOS 10\",\n                        description: \"Apple TV screensavers from tvOS 10\",\n                        manifestUrl: \"http://a1.phobos.apple.com/us/r1000/000/Features/atv/AutumnResources/videos/entries.json\",\n                        type: .tvOS10,\n                        scenes: [.nature, .city],\n                        isCachable: true,\n                        license: \"\",\n                        more: \"\")*/\n\n    static var list: [Source] = [macOS26, tvOS16, tvOS13] + foundSources\n    // static var list: [Source] = foundSources\n\n    // This is where the magic happens\n    static var foundSources: [Source] {\n        var sources: [Source] = []\n        var foundCommunity = false\n\n        for folder in URL(fileURLWithPath: Cache.supportPath).subDirectories {\n            if !folder.lastPathComponent.starts(with: \"tvOS\")\n                && !folder.lastPathComponent.starts(with: \"macOS\")\n                && !folder.lastPathComponent.starts(with: \"backups\")\n                && !folder.lastPathComponent.starts(with: \"Thumbnails\")\n                && !folder.lastPathComponent.starts(with: \"Cache\") {\n\n                if folder.lastPathComponent.starts(with: \"Community\") || folder.lastPathComponent.starts(with: \"From\") {\n                    foundCommunity = true\n                }\n\n                // If it's valid, let's add !\n                if let source = loadManifest(url: folder) {\n                    sources.append(source)\n                } else if let newsources = loadMetaManifest(url: folder) {\n                    sources.append(contentsOf: newsources)\n                }\n            }\n        }\n\n        if !foundCommunity {\n            DispatchQueue.main.async {\n                fetchOnlineManifest(url: URL(string: \"https://aerialscreensaver.github.io/community/\")!)\n            }\n        }\n\n        return sources\n    }\n\n    // swiftlint:disable for_where\n    static func hasNamed(name: String) -> Bool {\n        for source in list where source.type == .local {\n            if source.name == name {\n                return true\n            }\n        }\n\n        return false\n    }\n\n    static func categorizedSourceList() -> [SourceHeader] {\n        var communities: [Source] = []\n        var online: [Source] = []\n        var local: [Source] = []\n        var apple: [Source] = []\n\n        for source in list { // where !source.name.starts(with: \"tvOS\") {\n            if source.type == .local {\n                local.append(source)\n            } else {\n                // This may need to be changed in the future\n                if !source.isCachable {\n                    online.append(source)\n                } else if source.name.starts(with: \"tvOS\") || source.name.starts(with: \"macOS\") {\n                    apple.append(source)\n                } else {\n                    communities.append(source)\n                }\n            }\n        }\n\n        // Then we build our list\n        var output: [SourceHeader] = []\n\n        if !communities.isEmpty {\n            output.append(SourceHeader(name: \"Community Videos\", sources: communities))\n        }\n\n        if !online.isEmpty {\n            output.append(SourceHeader(name: \"Online Sources\", sources: online))\n        }\n\n        if !apple.isEmpty {\n            output.append(SourceHeader(name: \"Apple\", sources: apple))\n        }\n\n        if !local.isEmpty {\n            output.append(SourceHeader(name: \"Local Sources\", sources: local))\n        }\n\n        return output\n    }\n\n    static func fetchOnlineManifest(url: URL) {\n        if let source = loadManifest(url: url) {\n            debugLog(\"Source loaded\")\n            // Then save !\n            let downloadManager = DownloadManager()\n            downloadManager.queueDownload(url.appendingPathComponent(\"manifest.json\"), folder: source.name)\n\n            downloadManager.queueDownload(URL(string: source.manifestUrl)!, folder: source.name)\n            list.append(source)\n\n            source.setEnabled(true) // This will reload the main video list\n        } else if let sources = loadMetaManifest(url: url) {\n            debugLog(\"Sources loaded\")\n\n            for source in sources {\n                // Then save !\n                saveSource(source)\n\n                let downloadManager = DownloadManager()\n                downloadManager.queueDownload(URL(string: source.manifestUrl)!, folder: source.name)\n                list.append(source)\n\n                source.setEnabled(true) // This will reload the main video list\n            }\n        } else {\n            debugLog(\"Something went wrong here\")\n            let task = URLSession.shared.dataTask(with: url) { _, response, error in\n\n                if let error = error {\n                    debugLog(\"Can't load file, possible firewall issue\")\n                    DispatchQueue.main.async {\n                        Aerial.helper.showErrorAlert(question: \"An error occured loading the file\",\n                            text: \"Please check your network connection, firewall, and try again. \\n\\nError : \\(error.localizedDescription)\")\n                    }\n                    return\n                }\n                guard let response = response as? HTTPURLResponse else {\n                    debugLog(\"No HTTP response\")\n\n                    DispatchQueue.main.async {\n                        Aerial.helper.showErrorAlert(question: \"No HTTP Response\",\n                                              text: \"Please check your network connection, firewall, and try again.\")\n                    }\n                    return\n                }\n\n                if response.statusCode != 200 {\n                    DispatchQueue.main.async {\n                        debugLog(\"HTTP error\")\n\n                        Aerial.helper.showErrorAlert(question: \"HTTP Error\",\n                            text: \"Please verify the URL (and check your network connexion and firewall). HTTP error: \\(response.statusCode)\")\n                    }\n                    return\n                } else {\n                    DispatchQueue.main.async {\n                        debugLog(\"Incorect JSON format\")\n\n                        Aerial.helper.showErrorAlert(question: \"Incorrect JSON Format\",\n                                              text: \"Your URL was valid, but the file is not in the correct format. Please check the URL.\")\n                    }\n                    return\n                }\n            }\n            task.resume()\n        }\n    }\n\n    static func updateLocalSource(source: Source, reload: Bool) {\n        // We need the raw manifest to find the path inside\n        let videos = source.getUnprocessedVideos()\n        let originalAssets = source.getUnprocessedAssets()\n\n        var updatedAssets = [VideoAsset]()\n        \n        if videos.count >= 1 {\n            let url = videos.first!.url.deletingLastPathComponent()\n            let folderName = url.lastPathComponent\n            debugLog(\"processing url for videos : \\(url)\")\n\n            do {\n                let urls = try FileManager.default.contentsOfDirectory(at: url, includingPropertiesForKeys: nil, options: [.skipsHiddenFiles])\n                // var assets = [VideoAsset]()\n\n                \n                \n                for lurl in urls {\n                    if lurl.path.lowercased().hasSuffix(\".mp4\") || lurl.path.lowercased().hasSuffix(\".mov\") {\n                        let fileManager = FileManager.default\n                        let attributes = try? fileManager.attributesOfItem(atPath: lurl.path)\n                        let fileType = attributes?[.type] as? FileAttributeType\n                        let resourceValues = try lurl.resourceValues(forKeys: [.fileSizeKey])\n                        let fileSize = resourceValues.fileSize!\n\n                        if fileSize > 500000 || fileType == .typeSymbolicLink {\n                            // Check if the asset was there previously\n                            let foundAssets = originalAssets.filter { $0.url4KSDR == lurl.path }\n\n                            if let foundAsset = foundAssets.first {\n                                // Just add the asset to the new array\n                                updatedAssets.append(foundAsset)\n                            } else {\n                                // Create a new entry\n                                updatedAssets.append(VideoAsset(accessibilityLabel: folderName,\n                                                         id: NSUUID().uuidString,\n                                                         title: lurl.lastPathComponent,\n                                                         timeOfDay: \"day\",\n                                                         scene: \"\",\n                                                         pointsOfInterest: [:],\n                                                         url4KHDR: \"\",\n                                                         url4KSDR: lurl.path,\n                                                         url1080H264: \"\",\n                                                         url1080HDR: \"\",\n                                                         url4KSDR120FPS: \"\",\n                                                         url4KSDR240FPS: \"\",\n                                                         url1080SDR: \"\",\n                                                         url: \"\",\n                                                         type: \"nature\"))\n                            }\n\n                        }\n                    }\n                }\n\n                debugLog(\"Updating manifest \\(url.lastPathComponent)\")\n\n                let videoManifest = VideoManifest(assets: updatedAssets, initialAssetCount: 1, version: 1)\n\n                SourceList.saveEntries(source: source, manifest: videoManifest)\n\n                if reload {\n                    VideoList.instance.reloadSources()\n                }\n            } catch {\n                errorLog(\"Could not process directory\")\n            }\n        } else {\n            debugLog(\"Cannot parse your directory, did you delete your videos ?\")\n        }\n\n    }\n\n    static func processPathForVideos(url: URL) {\n        debugLog(\"processing url for videos : \\(url) \")\n        let folderName = url.lastPathComponent\n\n        do {\n            let urls = try FileManager.default.contentsOfDirectory(at: url, includingPropertiesForKeys: nil, options: [.skipsHiddenFiles])\n            var assets = [VideoAsset]()\n\n            for lurl in urls {\n                if lurl.path.lowercased().hasSuffix(\".mp4\") || lurl.path.lowercased().hasSuffix(\".mov\") {\n                    let fileManager = FileManager.default\n                    let attributes = try? fileManager.attributesOfItem(atPath: lurl.path)\n                    let fileType = attributes?[.type] as? FileAttributeType\n                    let resourceValues = try lurl.resourceValues(forKeys: [.fileSizeKey])\n                    let fileSize = resourceValues.fileSize!\n\n                    if fileSize > 500000 || fileType == .typeSymbolicLink {\n                        assets.append(VideoAsset(accessibilityLabel: folderName,\n                                                 id: NSUUID().uuidString,\n                                                 title: lurl.lastPathComponent,\n                                                 timeOfDay: \"day\",\n                                                 scene: \"\",\n                                                 pointsOfInterest: [:],\n                                                 url4KHDR: \"\",\n                                                 url4KSDR: lurl.path,\n                                                 url1080H264: \"\",\n                                                 url1080HDR: \"\",\n                                                 url4KSDR120FPS: \"\",\n                                                 url4KSDR240FPS: \"\",\n                                                 url1080SDR: \"\",\n                                                 url: \"\",\n                                                 type: \"nature\"))\n                    }\n                }\n            }\n\n            // ...\n            if SourceList.hasNamed(name: url.lastPathComponent) {\n                Aerial.helper.showInfoAlert(title: \"Source name mismatch\",\n                                     text: \"A source with this name already exists. Try renaming your folder and try again.\")\n            } else {\n                debugLog(\"Creating source \\(url.lastPathComponent)\")\n\n                // Generate and save the Source\n                let source = Source(name: url.lastPathComponent,\n                                    description: \"Local files from \\(url.path)\",\n                                    manifestUrl: \"manifest.json\",\n                                    type: .local,\n                                    scenes: [.nature],\n                                    isCachable: false,\n                                    license: \"\",\n                                    more: \"\")\n\n                SourceList.saveSource(source)\n\n                // Then the entries\n                let videoManifest = VideoManifest(assets: assets, initialAssetCount: 1, version: 1)\n\n                SourceList.saveEntries(source: source, manifest: videoManifest)\n\n                list.append(source)\n                VideoList.instance.reloadSources()\n            }\n        } catch {\n            errorLog(\"Could not process directory\")\n        }\n    }\n\n    static func saveSource(_ source: Source) {\n        let manifest = Manifest.init(name: source.name,\n                                     manifestDescription: source.description,\n                                     scenes: source.scenes.map({ $0.rawValue }),\n                                     local: source.type == .local,\n                                     cacheable: source.isCachable,\n                                     manifestUrl: source.manifestUrl,\n                                     license: source.license,\n                                     more: source.more)\n\n        // First make the folder\n        FileHelpers.createDirectory(atPath: Cache.supportPath.appending(\"/\"+source.name))\n\n        let json = try? JSONEncoder().encode(manifest)\n\n        do {\n            try json!.write(to: URL(fileURLWithPath:\n                                    Cache.supportPath.appending(\"/\"+source.name+\"/manifest.json\")))\n        } catch {\n            errorLog(\"Can't save local source : \\(error.localizedDescription)\")\n        }\n    }\n\n    static func saveEntries(source: Source, manifest: VideoManifest) {\n        let json = try? JSONEncoder().encode(manifest)\n\n        do {\n            try json!.write(to: URL(fileURLWithPath:\n                                    Cache.supportPath.appending(\"/\"+source.name+\"/entries.json\")))\n        } catch {\n            errorLog(\"Can't save local entries : \\(error.localizedDescription)\")\n        }\n    }\n    static func loadMetaManifest(url: URL) -> [Source]? {\n        // Let's make sure we have the required files\n        if !areManifestPresent(url: url) && !url.absoluteString.starts(with: \"http\") {\n            return nil\n        }\n\n        do {\n            let jsonData = try Data(contentsOf: url.appendingPathComponent(\"manifest.json\"))\n\n            if let metamanifest = try? newJSONDecoder().decode(MetaManifest.self, from: jsonData) {\n                var sources: [Source] = []\n\n                for manifest in metamanifest.sources {\n                    sources.append(parseSourceFromManifest(manifest, url: url))\n                }\n\n                return sources\n            }\n        } catch {\n            errorLog(\"Could not open manifest for source at \\(url)\")\n            return nil\n        }\n\n        return nil\n    }\n\n    static func loadManifest(url: URL) -> Source? {\n        // Let's make sure we have the required files\n        if !areManifestPresent(url: url) && !url.absoluteString.starts(with: \"http\") {\n            return nil\n        }\n\n        do {\n            let jsonData = try Data(contentsOf: url.appendingPathComponent(\"manifest.json\"))\n            if let manifest = try? newJSONDecoder().decode(Manifest.self, from: jsonData) {\n                debugLog(\"Manifest opened, going to parsing\")\n                return parseSourceFromManifest(manifest, url: nil)\n            }\n        } catch {\n            errorLog(\"Could not open manifest for source at \\(url)\")\n            return nil\n        }\n\n        return nil\n    }\n\n    static private func parseSourceFromManifest(_ manifest: Manifest, url: URL?) -> Source {\n        var local = true\n        var mURL: String\n        if let isLocal = manifest.local {\n            local = isLocal\n        }\n\n        if local {\n            mURL = (url != nil) ? url!.absoluteString : manifest.manifestUrl ?? \"\"\n        } else {\n            mURL = manifest.manifestUrl ?? \"\"\n        }\n\n        let cacheable: Bool = manifest.cacheable ?? !local\n\n        debugLog(\"Parsed \\(manifest.name)\")\n\n        return Source(name: manifest.name,\n                      description: manifest.manifestDescription,\n                      manifestUrl: mURL,\n                      type: local ? .local : .tvOS12,\n                      scenes: jsonToSceneArray(array: manifest.scenes ?? []),\n                      isCachable: cacheable,\n                      license: manifest.license ?? \"\",\n                      more: manifest.more ?? \"\")\n    }\n\n    /// Helper to convert an array of strings to an array of sources\n    ///\n    /// [\"landscape\"] -> [.landscape]\n    static func jsonToSceneArray(array: [String]) -> [SourceScene] {\n        var output: [SourceScene] = []\n        for scene in array {\n            switch scene {\n            case \"sea\":\n                output.append(.sea)\n            case \"space\":\n                output.append(.space)\n            case \"city\":\n                output.append(.city)\n            case \"beach\":\n                output.append(.beach)\n            case \"countryside\":\n                output.append(.countryside)\n            default:\n                output.append(.nature)\n            }\n        }\n\n        return output\n    }\n\n    static func areManifestPresent(url: URL) -> Bool {\n        // For a source to be valid we at the very least need two things\n        // manifest.json    <- a description of the source\n        // entries.json     <- the classic video manifest\n        return FileManager.default.fileExists(atPath: url.path.appending(\"/entries.json\")) ||\n           FileManager.default.fileExists(atPath: url.path.appending(\"/manifest.json\"))\n    }\n\n}\n\n// MARK: - MetaManifest\nstruct MetaManifest: Codable {\n    let sources: [Manifest]\n}\n\n// MARK: - Manifest\nstruct Manifest: Codable {\n    let name, manifestDescription: String\n    let scenes: [String]?\n    let local: Bool?\n    let cacheable: Bool?\n    let manifestUrl: String?\n    let license: String?\n    let more: String?\n\n    enum CodingKeys: String, CodingKey {\n        case name\n        case manifestDescription = \"description\"\n        case scenes\n        case local\n        case cacheable\n        case manifestUrl\n        case license\n        case more\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Models/Sources/VideoList.swift",
    "content": "//\n//  VideoList.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 08/07/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Foundation\n\ntypealias VideoListRefreshCallback = () -> Void\nextension RangeReplaceableCollection {\n    /// Returns a collection containing, in order, the first instances of\n    /// elements of the sequence that compare equally for the keyPath.\n    func unique<T: Hashable>(for keyPath: KeyPath<Element, T>) -> Self {\n        var unique = Set<T>()\n        return filter { unique.insert($0[keyPath: keyPath]).inserted }\n    }\n}\n\n// swiftlint:disable:next type_body_length\nclass VideoList {\n    enum FilterMode {\n        case location, cache, time, scene, source, rotation, favorite, hidden\n    }\n\n    static let instance: VideoList = VideoList()\n    var callbacks = [VideoListRefreshCallback]()\n\n    var videos: [AerialVideo] = []\n\n    // OLD Playlist management\n    var playlistIsRestricted = false\n    var playlistRestrictedTo = \"\"\n    var playlistHasVerticalVideos = false\n    var playlist = [AerialVideo]()\n    var playlistForScreen: [String:[AerialVideo]] = [:]\n    var lastPluckedFromPlaylist: AerialVideo?\n\n    let cacheDownloaded = \"Downloaded\"\n    let cacheOnline = \"Online\"\n    init() {\n        downloadManifestsIfNeeded()\n    }\n\n    func videoForFilename(_ name: String) -> AerialVideo? {\n        for video in videos where video.url.lastPathComponent == name {\n            return video\n        }\n\n        errorLog(\"vFF unknown video filename\")\n        return nil\n    }\n\n    // This is used to grab the correct path depending on whether a source is cacheable or not\n    func localPathFor(video: AerialVideo) -> String {\n        if video.source.isCachable {\n            return VideoCache.cachePath(forVideo: video) ?? \"\"\n        } else {\n            return VideoCache.sourcePathFor(video)\n        }\n    }\n\n    // MARK: - Helpers for the various filterings\n    private func cacheSources() -> [String] {\n        var cache: [String] = []\n\n        if !videos.filter({ $0.isAvailableOffline && !PrefsVideos.hidden.contains($0.id) }).isEmpty {\n            cache.append(cacheDownloaded)\n        }\n        if !videos.filter({ !$0.isAvailableOffline && !PrefsVideos.hidden.contains($0.id) }).isEmpty {\n            cache.append(cacheOnline)\n        }\n\n        return cache\n    }\n\n    private func sourcesFor(_ mode: FilterMode) -> [String] {\n        switch mode {\n        case .location:\n            return videos.filter { !PrefsVideos.hidden.contains($0.id) }.map { $0.name }.unique(for: \\.self)\n        case .time:\n            return videos.filter { !PrefsVideos.hidden.contains($0.id) }.map { $0.timeOfDay.capitalizeFirstLetter() }.unique(for: \\.self)\n        case .scene:\n            return videos.filter { !PrefsVideos.hidden.contains($0.id) }.map { $0.scene.rawValue.capitalizeFirstLetter() }.unique(for: \\.self)\n        case .source:\n            return videos.filter { !PrefsVideos.hidden.contains($0.id) }.map { $0.source.name }.unique(for: \\.self)\n        case .cache:\n            return cacheSources()\n        case .rotation:\n            return [\"On Rotation\"]\n        case .favorite:\n            return [\"Favorites\"]\n        case .hidden:\n            return [\"Hidden\"]\n        }\n    }\n\n    private func filteredVideosFor(_ mode: FilterMode, section: Int) -> [AerialVideo] {\n        switch mode {\n        case .location:\n            let filter = sourcesFor(mode)[section].lowercased()\n            return videos\n                .filter { $0.name.lowercased() == filter && !PrefsVideos.hidden.contains($0.id) }\n                .sorted { $0.secondaryName < $1.secondaryName }\n        case .time:\n            let filter = sourcesFor(mode)[section].lowercased()\n            return videos\n                .filter { $0.timeOfDay.lowercased() == filter && !PrefsVideos.hidden.contains($0.id) }\n                .sorted { $0.secondaryName < $1.secondaryName }\n        case .scene:\n            let filter = sourcesFor(mode)[section].lowercased()\n            return videos\n                .filter { $0.scene.rawValue.lowercased() == filter && !PrefsVideos.hidden.contains($0.id) }\n                .sorted { $0.secondaryName < $1.secondaryName }\n        case .source:\n            let filter = sourcesFor(mode)[section].lowercased()\n            return videos\n                .filter { $0.source.name.lowercased() == filter && !PrefsVideos.hidden.contains($0.id) }\n                .sorted { $0.secondaryName < $1.secondaryName }\n        case .cache:\n            // TODO FIX THIS IT CRASHES WHEN YOU FAV FROM ONLINE\n            // if let cacheSources().\n            if cacheSources()[section] == cacheDownloaded {\n                return videos\n                    .filter({ $0.isAvailableOffline && !PrefsVideos.hidden.contains($0.id) })\n                    .sorted { $0.secondaryName < $1.secondaryName }\n            } else {\n                return videos\n                    .filter({ !$0.isAvailableOffline && !PrefsVideos.hidden.contains($0.id) })\n                    .sorted { $0.secondaryName < $1.secondaryName }\n            }\n        case .rotation:\n            return currentRotation()    // Result is already sorted there\n        case .favorite:\n            return videos\n                .filter { PrefsVideos.favorites.contains($0.id) && !PrefsVideos.hidden.contains($0.id)}\n                .sorted { $0.secondaryName < $1.secondaryName }\n        case .hidden:\n            return videos\n                .filter { PrefsVideos.hidden.contains($0.id) }\n                .sorted { $0.secondaryName < $1.secondaryName }\n        }\n\n    }\n\n    // swiftlint:disable:next cyclomatic_complexity\n    private func filteredVideosFor(_ mode: FilterMode, filter: [String]) -> [AerialVideo] {\n        // Our preference filters contains ALL sorts of filters (location, time) that are\n        // saved for better user experience. So we need to filter the filters first !\n        var filters: [String] = []\n\n        for afilter in filter {\n            switch mode {\n            case .location:\n                if afilter.starts(with: \"location\") {\n                    filters.append(afilter.split(separator: \":\")[1].lowercased())\n                }\n            case .cache:\n                filters.append(afilter.lowercased())\n            case .time:\n                if afilter.starts(with: \"time\") {\n                    filters.append(afilter.split(separator: \":\")[1].lowercased())\n                }\n            case .scene:\n                if afilter.starts(with: \"scene\") {\n                    filters.append(afilter.split(separator: \":\")[1].lowercased())\n                }\n            case .source:\n                if afilter.starts(with: \"source\") {\n                    filters.append(afilter.split(separator: \":\")[1].lowercased())\n                }\n            case .rotation:\n                filters.append(afilter.lowercased())\n            case .favorite:\n                filters.append(afilter.lowercased())\n            case .hidden:\n                filters.append(afilter.lowercased())\n            }\n        }\n\n        switch mode {\n        case .location:\n            let vids = videos\n                .filter { filters.contains($0.name.lowercased()) && !PrefsVideos.hidden.contains($0.id) }\n                .sorted { $0.secondaryName < $1.secondaryName }\n            return vids\n        case .time:\n            return videos\n                .filter { filters.contains($0.timeOfDay.lowercased()) && !PrefsVideos.hidden.contains($0.id) }\n                .sorted { $0.secondaryName < $1.secondaryName }\n        case .scene:\n            return videos\n                .filter { filters.contains($0.scene.rawValue.lowercased()) && !PrefsVideos.hidden.contains($0.id) }\n                .sorted { $0.secondaryName < $1.secondaryName }\n        case .source:\n            return videos\n                .filter { filters.contains($0.source.name.lowercased()) && !PrefsVideos.hidden.contains($0.id) }\n                .sorted { $0.secondaryName < $1.secondaryName }\n        case .favorite:\n            return videos\n                .filter { PrefsVideos.favorites.contains($0.id) && !PrefsVideos.hidden.contains($0.id) }\n                .sorted { $0.secondaryName < $1.secondaryName }\n        case .hidden:\n            return videos\n                .filter { PrefsVideos.hidden.contains($0.id) }\n                .sorted { $0.secondaryName < $1.secondaryName }\n        default:\n            return videos\n                .filter({ $0.isAvailableOffline })\n                .sorted { $0.secondaryName < $1.secondaryName }\n        }\n    }\n\n    // MARK: - Public getters to filter the list\n    func getSources(mode: FilterMode) -> [String] {\n        return sourcesFor(mode)\n    }\n\n    func getSourcesCount(mode: FilterMode) -> Int {\n        return sourcesFor(mode).count\n    }\n\n    func getSourceName(_ section: Int, mode: FilterMode) -> String {\n        return sourcesFor(mode)[section]\n    }\n\n    func getVideosCountForSource(_ section: Int, mode: FilterMode) -> Int {\n        return filteredVideosFor(mode, section: section).count\n    }\n\n    func getVideoForSource(_ section: Int, item: Int, mode: FilterMode) -> AerialVideo {\n        return filteredVideosFor(mode, section: section)[item]\n    }\n\n    func getVideosForSource(_ section: Int, mode: FilterMode) -> [AerialVideo] {\n        return filteredVideosFor(mode, section: section)\n    }\n\n    // MARK: - Public getter for a video list from paths\n    func getVideosForPath(_ path: String) -> [AerialVideo] {\n        if let mode = VideoList.instance.modeFromPath(path) {\n            let index = Int(path.split(separator: \":\")[1])!\n            return VideoList.instance.getVideosForSource(index, mode: mode)\n        } else {\n            // all\n            return VideoList.instance.videos.filter({ !PrefsVideos.hidden.contains($0.id) }).sorted { $0.secondaryName < $1.secondaryName }\n        }\n    }\n\n    func modeFromPath(_ path: String) -> FilterMode? {\n        if path.starts(with: \"location\") {\n            return .location\n        } else if path.starts(with: \"cache\") {\n            return .cache\n        } else if path.starts(with: \"time\") {\n            return .time\n        } else if path.starts(with: \"scene\") {\n            return .scene\n        } else if path.starts(with: \"rotation\") {\n            return .rotation\n        } else if path.starts(with: \"source\") {\n            return .source\n        } else if path.starts(with: \"favorites\") {\n            return .favorite\n        } else if path.starts(with: \"hidden\") {\n            return .hidden\n        } else {\n            return nil\n        }\n    }\n\n    // MARK: - Callbacks\n    func addCallback(_ callback:@escaping VideoListRefreshCallback) {\n        callbacks.append(callback)\n\n        // We may need to insta callback if we were already inited\n        if !videos.isEmpty {\n            callback()\n        }\n    }\n\n    // This is how we force a source refresh, it will trigger various callbacks when done\n    // (e.g. to refresh video list in the ui)\n    func reloadSources() {\n        videos = []\n        downloadManifestsIfNeeded()\n    }\n\n    func downloadSource(source: Source) {\n        let downloadManager = DownloadManager()\n\n        let completion = BlockOperation {\n            self.refreshVideoList()\n            if !PrefsCache.enableManagement {\n                Aerial.helper.showInfoAlert(title: \"Automatic downloads are disabled\", text: \"In order to watch the new videos, you will need to manually download them (for example by pressing the down arrow button on the right).\")\n            }\n        }\n\n        for src in SourceList.list where source.name == src.name {\n            debugLog(\"Marking \\(source.name) for redownload\")\n            // Then queue the download\n            let operation = downloadManager.queueDownload(URL(string: source.manifestUrl)!, folder: source.name)\n            completion.addDependency(operation)\n\n            OperationQueue.main.addOperation(completion)\n        }\n    }\n\n    private func downloadManifestsIfNeeded() {\n        let downloadManager = DownloadManager()\n\n        var sourceQueue: [Source] = []\n\n        let completion = BlockOperation {\n            self.refreshVideoList()\n        }\n\n        // Let's check our sources first\n        for source in SourceList.list {\n            // But only the enabled ones\n            if source.isEnabled() {\n                // We may need to download it\n                if !source.isCached() {\n                    debugLog(\"\\(source.name) is not cached, downloading...\")\n                    sourceQueue.append(source)\n                } else if PrefsVideos.shouldCheckForNewVideos() && Cache.canNetwork() {\n                    debugLog(\"\\(source.name) looking for updated manifest...\")\n                    sourceQueue.append(source)\n                } else {\n                    debugLog(\"\\(source.name) is enabled, cached and up to date\")\n                }\n            }\n        }\n\n        for source in SourceList.list {\n            if source.type == .local {\n                debugLog(\"\\(source.name) updating local source\")\n                SourceList.updateLocalSource(source: source, reload: false)\n            }\n        }\n\n        if !sourceQueue.isEmpty {\n            // Now queue and download\n            for source in sourceQueue {\n                // Then queue the download\n                let operation = downloadManager.queueDownload(URL(string: source.manifestUrl)!, folder: source.name)\n                completion.addDependency(operation)\n\n                // Mark that we updated our sources\n                PrefsVideos.saveLastVideoCheck()\n            }\n\n            OperationQueue.main.addOperation(completion)\n        } else {\n            DispatchQueue.main.async {\n                self.refreshVideoList()\n            }\n        }\n    }\n\n    // This is called when all our files are downloaded\n    private func refreshVideoList() {\n        debugLog(\"Refreshing video list\")\n\n        videos = []\n\n        for source in SourceList.list {\n            if source.isEnabled() {\n                // We may need to download it\n                if source.isCached() {\n                    let vids = source.getVideos()\n                    videos.append(contentsOf: vids)\n                    debugLog(\"source : \\(source.name) contains \\(vids.count) new videos (total \\(videos.count))\")\n                }\n            }\n        }\n\n        videos = videos.sorted { $0.name < $1.name }\n\n        // Let everyone who wants to know that our list is updated\n        for callback in callbacks {\n            callback()\n        }\n    }\n\n    // MARK: - New rotation management\n    func currentRotation() -> [AerialVideo] {\n        var mode: FilterMode\n        switch PrefsVideos.newShouldPlay {\n        case .location:\n            mode = .location\n        case .time:\n            mode = .time\n        case .scene:\n            mode = .scene\n        case .source:\n            mode = .source\n        default:\n            mode = .cache\n        }\n\n        switch PrefsVideos.newShouldPlay {\n/*        case .everything:\n            return videos\n                .filter({ !PrefsVideos.hidden.contains($0.id) })\n                .sorted { $0.secondaryName < $1.secondaryName }*/\n        case .favorites:\n            return videos\n                .filter({ PrefsVideos.favorites.contains($0.id) && !PrefsVideos.hidden.contains($0.id) })\n                .sorted { $0.secondaryName < $1.secondaryName }\n        default:\n            print(PrefsVideos.newShouldPlayString)\n            return filteredVideosFor(mode, filter: PrefsVideos.newShouldPlayString)\n        }\n    }\n    \n    func everythingRotation() -> [AerialVideo] {\n        return videos\n            .filter({ !PrefsVideos.hidden.contains($0.id) })\n            .sorted { $0.secondaryName < $1.secondaryName }\n    }\n\n    // MARK: - Playlist management\n    func generatePlaylist(isRestricted: Bool, restrictedTo: String, isVertical: Bool) {\n        debugLog(\"generate playlist (isVertical: \\(isVertical)\")\n        // Start fresh\n        playlist = [AerialVideo]()\n        playlistIsRestricted = isRestricted\n        playlistRestrictedTo = restrictedTo\n        playlistHasVerticalVideos = false\n\n        var shuffled = currentRotation().shuffled()\n\n        // If we have nothing, just get everything\n        if shuffled.count == 0 {\n            shuffled = everythingRotation().shuffled()\n        }\n        \n        let cachedShuffled = shuffled.filter({ $0.isAvailableOffline })\n\n        \n        debugLog(\"Playlist raw count: \\(shuffled.count) raw cached count \\(cachedShuffled.count) isRestricted: \\(isRestricted) restrictedTo: \\(restrictedTo)\")\n\n        if PrefsDisplays.viewingMode == .independent && PrefsAdvanced.favorOrientation {\n            // We check cached videos only as those are the only ones for which we know the orientation\n            for video in cachedShuffled {\n                // swiftlint:disable:next for_where\n                if video.isVertical {\n                    playlistHasVerticalVideos = true\n                    debugLog(\">>> Playlist contains vertical videos (favoring ON)\")\n                }\n            }\n        }\n\n        for video in shuffled {\n            /*\n            // Do we restrict videos by screen orientation ?\n            if restrictOrientation {\n                print(video.url)\n                print(video.isVertical)\n                if !video.isVertical && isVertical {\n                    // Block landscape videos on vertical screens\n                    continue\n                } else if video.isVertical && !isVertical {\n                    // Block portrait videos on horizontal screens\n                    continue\n                }\n            }*/\n\n            // Do we restrict video types by day/night ?\n            if isRestricted {\n                if video.timeOfDay != restrictedTo {\n                    continue\n                }\n            }\n\n            if !video.isAvailableOffline {\n                continue\n            }\n\n            // All good ? Add to playlist\n            playlist.append(video)\n        }\n\n        debugLog(\"Final count : \\(playlist.count)\")\n        // On regenerating a new playlist, we try to avoid repeating the last thing we played!\n        while playlist.count > 1 && lastPluckedFromPlaylist == playlist.first {\n            playlist.shuffle()\n        }\n    }\n\n    func randomVideo(excluding: [AerialVideo], isVertical: Bool) -> (AerialVideo?, Bool) {\n        var shouldLoop = false\n        let timeManagement = TimeManagement.sharedInstance\n\n        let (shouldRestrictByDayNight, restrictTo) = timeManagement.shouldRestrictPlaybackToDayNightVideo()\n\n        // Do we still have a video in the correct format in the playlist?\n        var needOrientedVideo = false\n        if playlistHasVerticalVideos && !playlist.isEmpty {\n            needOrientedVideo = true\n            for video in playlist {\n                if isVertical && video.isVertical {\n                    needOrientedVideo = false\n                } else if !isVertical && !video.isVertical {\n                    needOrientedVideo = false\n                }\n            }\n        }\n\n        debugLog(\"remaining in playlist : \\(playlist.count) needOrientedVideo : \\(needOrientedVideo)\")\n\n        // We may need to regenerate a playlist!\n        if playlist.isEmpty || restrictTo != playlistRestrictedTo || shouldRestrictByDayNight != playlistIsRestricted || needOrientedVideo {\n            generatePlaylist(isRestricted: shouldRestrictByDayNight, restrictedTo: restrictTo, isVertical: isVertical)\n            if playlist.count == 1 {\n                debugLog(\"playlist only has one element, looping!\")\n                shouldLoop = true\n            }\n        }\n\n        // If not pluck one from current playlist and return that\n        if !playlist.isEmpty {\n            if playlistHasVerticalVideos {\n                lastPluckedFromPlaylist = pluckOrientedVideo(isVertical: isVertical)\n            } else {\n                lastPluckedFromPlaylist = playlist.removeFirst()\n            }\n\n            return (lastPluckedFromPlaylist, shouldLoop)\n        } else {\n            // If we don't have any playlist, something's got awfully wrong so deal with that!\n            return (findBestEffortVideo(), shouldLoop)\n        }\n    }\n\n    func pluckOrientedVideo(isVertical: Bool) -> AerialVideo? {\n        // Grab first one corresponding to orientation\n        lastPluckedFromPlaylist = playlist.first(where: { $0.isVertical == isVertical })!\n        debugLog(\"lastplucked\")\n\n        // And actually remove it\n        debugLog(\"pre pluck \\(playlist.count)\")\n        playlist = playlist.filter { $0 != lastPluckedFromPlaylist }\n        debugLog(\"post pluck \\(playlist.count)\")\n\n        return lastPluckedFromPlaylist\n    }\n\n    // Find a backup plan when conditions are not met\n    func findBestEffortVideo() -> AerialVideo? {\n        // So this is embarassing. This can happen if :\n        // - No video checked\n        // - No video for current conditions (only day video checked, and looking for night)\n        // - We don't want to stream but don't have any video\n        // - We may not have the manifests\n        // At this point we're doing a best effort :\n        // - Did we play something previously ? If so play that back (will loop)\n        // - return a random one from the manifest that is cached\n        // - return a random video that is not cached (slight betrayal of the Never stream videos)\n\n        warnLog(\"Empty playlist, not good !\")\n\n        if lastPluckedFromPlaylist != nil {\n            warnLog(\"Repeating last played video, after condition change not met !\")\n            return lastPluckedFromPlaylist!\n        } else {\n            // Start with a shuffled list\n            let shuffled = videos.shuffled()\n\n            if shuffled.isEmpty {\n                // This is super bad, no manifest at all\n                errorLog(\"No manifest, nothing to play !\")\n                return nil\n            }\n\n            for video in shuffled {\n                // If we find anything cached and in rotation, we send that back\n                if video.isAvailableOffline && currentRotation().contains(video) {\n                    warnLog(\"returning random cached in rotation video after condition change not met !\")\n                    return video\n                }\n            }\n\n            // We try to return something that's at least in the rotation, if there is one\n            if !currentRotation().isEmpty {\n                warnLog(\"returning random non cached BUT in rotation video after condition change not met !\")\n                return currentRotation().shuffled().first\n            }\n\n            // Really nothing ? I can't even !\n            warnLog(\"returning truly random video after condition change not met !\")\n            return shuffled.first!\n        }\n    }\n\n}\n"
  },
  {
    "path": "Aerial/Source/Models/Time/Aerial-Bridging-Header.h",
    "content": "//\n//  Use this file to import your target's public headers that you would like to expose to Swift.\n//\n\n// We need this to be able to use IOPowerSources for battery status detection in Swift\n#import <IOKit/ps/IOPowerSources.h>\n"
  },
  {
    "path": "Aerial/Source/Models/Time/IOBridge.m",
    "content": "//\n//  IOBridge.m\n//  Aerial\n//\n//  Created by Guillaume Louel on 26/10/2018.\n//  Copyright © 2018 John Coates. All rights reserved.\n//\n// We need this to be able to use IOPowerSources for battery status detection in Swift\n\n#import <Foundation/Foundation.h>\n"
  },
  {
    "path": "Aerial/Source/Models/Time/Solar.swift",
    "content": "//\n//  Solar.swift\n//  SolarExample\n//\n//  Created by Chris Howell on 16/01/2016.\n//  Copyright © 2016 Chris Howell. All rights reserved.\n//\n//  Permission is hereby granted, free of charge, to any person obtaining a copy\n//  of this software and associated documentation files (the “Software”), to deal\n//  in the Software without restriction, including without limitation the rights\n//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n//  copies of the Software, and to permit persons to whom the Software is\n//  furnished to do so, subject to the following conditions:\n//\n//  The above copyright notice and this permission notice shall be included in\n//  all copies or substantial portions of the Software.\n//\n//  THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n//  THE SOFTWARE.\n//\n//  Modifications for Aerial/glouel\n//      26/10/2018: - added an intermediate mode that's closer to night shift sunset/sunrise times\n//                  - added a isDaylight(zenith: Zenith) function\n\nimport Foundation\nimport CoreLocation\n\npublic struct Solar {\n\n    /// The coordinate that is used for the calculation\n    public let coordinate: CLLocationCoordinate2D\n\n    /// The date to generate sunrise / sunset times for\n    public fileprivate(set) var date: Date\n\n    public fileprivate(set) var sunrise: Date?\n    public fileprivate(set) var sunset: Date?\n    public fileprivate(set) var civilSunrise: Date?\n    public fileprivate(set) var civilSunset: Date?\n    public fileprivate(set) var strictSunrise: Date?\n    public fileprivate(set) var strictSunset: Date?\n    public fileprivate(set) var nauticalSunrise: Date?\n    public fileprivate(set) var nauticalSunset: Date?\n    public fileprivate(set) var astronomicalSunrise: Date?\n    public fileprivate(set) var astronomicalSunset: Date?\n\n    // MARK: Init\n\n    public init?(for date: Date = Date(), coordinate: CLLocationCoordinate2D) {\n        self.date = date\n\n        guard CLLocationCoordinate2DIsValid(coordinate) else {\n            return nil\n        }\n\n        self.coordinate = coordinate\n\n        // Fill this Solar object with relevant data\n        calculate()\n    }\n\n    // MARK: - Public functions\n\n    /// Sets all of the Solar object's sunrise / sunset variables, if possible.\n    /// - Note: Can return `nil` objects if sunrise / sunset does not occur on that day.\n    public mutating func calculate() {\n        strictSunrise = calculate(.sunrise, for: date, and: .strict)\n        strictSunset = calculate(.sunset, for: date, and: .strict)\n        sunrise = calculate(.sunrise, for: date, and: .official)\n        sunset = calculate(.sunset, for: date, and: .official)\n        civilSunrise = calculate(.sunrise, for: date, and: .civil)\n        civilSunset = calculate(.sunset, for: date, and: .civil)\n        nauticalSunrise = calculate(.sunrise, for: date, and: .nautical)\n        nauticalSunset = calculate(.sunset, for: date, and: .nautical)\n        astronomicalSunrise = calculate(.sunrise, for: date, and: .astronimical)\n        astronomicalSunset = calculate(.sunset, for: date, and: .astronimical)\n    }\n\n    // MARK: - Private functions\n\n    fileprivate enum SunriseSunset {\n        case sunrise\n        case sunset\n    }\n\n    /// Used for generating several of the possible sunrise / sunset times\n    public enum Zenith: Double {\n        case strict = 90\n        case official = 90.83\n        case civil = 96\n        case nautical = 102\n        case astronimical = 108\n    }\n\n    // swiftlint:disable identifier_name\n    fileprivate func calculate(_ sunriseSunset: SunriseSunset, for date: Date, and zenith: Zenith) -> Date? {\n        guard let utcTimezone = TimeZone(identifier: \"UTC\") else { return nil }\n\n        // Get the day of the year\n        var calendar = Calendar(identifier: .gregorian)\n        calendar.timeZone = utcTimezone\n        guard let dayInt = calendar.ordinality(of: .day, in: .year, for: date) else { return nil }\n        let day = Double(dayInt)\n\n        // Convert longitude to hour value and calculate an approx. time\n        let lngHour = coordinate.longitude / 15\n\n        let hourTime: Double = sunriseSunset == .sunrise ? 6 : 18\n        let t = day + ((hourTime - lngHour) / 24)\n\n        // Calculate the suns mean anomaly\n        let M = (0.9856 * t) - 3.289\n\n        // Calculate the sun's true longitude\n        let subexpression1 = 1.916 * sin(M.degreesToRadians)\n        let subexpression2 = 0.020 * sin(2 * M.degreesToRadians)\n        var L = M + subexpression1 + subexpression2 + 282.634\n\n        // Normalise L into [0, 360] range\n        L = normalise(L, withMaximum: 360)\n\n        // Calculate the Sun's right ascension\n        var RA = atan(0.91764 * tan(L.degreesToRadians)).radiansToDegrees\n\n        // Normalise RA into [0, 360] range\n        RA = normalise(RA, withMaximum: 360)\n\n        // Right ascension value needs to be in the same quadrant as L...\n        let Lquadrant = floor(L / 90) * 90\n        let RAquadrant = floor(RA / 90) * 90\n        RA += (Lquadrant - RAquadrant)\n\n        // Convert RA into hours\n        RA /= 15\n\n        // Calculate Sun's declination\n        let sinDec = 0.39782 * sin(L.degreesToRadians)\n        let cosDec = cos(asin(sinDec))\n\n        // Calculate the Sun's local hour angle\n        let cosH = (cos(zenith.rawValue.degreesToRadians) - (sinDec * sin(coordinate.latitude.degreesToRadians))) / (cosDec * cos(coordinate.latitude.degreesToRadians))\n\n        // No sunrise\n        guard cosH < 1 else {\n            return nil\n        }\n\n        // No sunset\n        guard cosH > -1 else {\n            return nil\n        }\n\n        // Finish calculating H and convert into hours\n        let tempH = sunriseSunset == .sunrise ? 360 - acos(cosH).radiansToDegrees : acos(cosH).radiansToDegrees\n        let H = tempH / 15.0\n\n        // Calculate local mean time of rising\n        let T = H + RA - (0.06571 * t) - 6.622\n\n        // Adjust time back to UTC\n        var UT = T - lngHour\n\n        // Normalise UT into [0, 24] range\n        UT = normalise(UT, withMaximum: 24)\n\n        // Calculate all of the sunrise's / sunset's date components\n        let hour = floor(UT)\n        let minute = floor((UT - hour) * 60.0)\n        let second = (((UT - hour) * 60) - minute) * 60.0\n\n        let shouldBeYesterday = lngHour > 0 && UT > 12 && sunriseSunset == .sunrise\n        let shouldBeTomorrow = lngHour < 0 && UT < 12 && sunriseSunset == .sunset\n\n        let setDate: Date\n        if shouldBeYesterday {\n            setDate = Date(timeInterval: -(60 * 60 * 24), since: date)\n        } else if shouldBeTomorrow {\n            setDate = Date(timeInterval: (60 * 60 * 24), since: date)\n        } else {\n            setDate = date\n        }\n\n        var components = calendar.dateComponents([.day, .month, .year], from: setDate)\n        components.hour = Int(hour)\n        components.minute = Int(minute)\n        components.second = Int(second)\n\n        calendar.timeZone = utcTimezone\n        return calendar.date(from: components)\n    }\n    // swiftlint:enable identifier_name\n\n    /// Normalises a value between 0 and `maximum`, by adding or subtracting `maximum`\n    fileprivate func normalise(_ value: Double, withMaximum maximum: Double) -> Double {\n        var value = value\n\n        if value < 0 {\n            value += maximum\n        }\n\n        if value > maximum {\n            value -= maximum\n        }\n\n        return value\n    }\n\n}\n\nextension Solar {\n\n    /// Whether the location specified by the `latitude` and `longitude` is in daytime on `date`\n    /// - Complexity: O(1)\n    public var isDaytime: Bool {\n        guard\n            let sunrise = sunrise,\n            let sunset = sunset\n            else {\n                return false\n        }\n\n        let beginningOfDay = sunrise.timeIntervalSince1970\n        let endOfDay = sunset.timeIntervalSince1970\n        let currentTime = self.date.timeIntervalSince1970\n\n        let isSunriseOrLater = currentTime >= beginningOfDay\n        let isBeforeSunset = currentTime < endOfDay\n\n        return isSunriseOrLater && isBeforeSunset\n    }\n\n    /// Whether the location specified by the `latitude` and `longitude` is in nighttime on `date`\n    /// - Complexity: O(1)\n    public var isNighttime: Bool {\n        return !isDaytime\n    }\n\n    /// Whether the location specified by the `latitude` and `longitude` is in daytime on `date`\n    /// Takes an extra Zenith parameter to handle all cases\n    /// - Complexity: O(1)\n    public func isDaytime(zenith: Zenith) -> Bool {\n        guard\n            let _ = sunrise,\n            let _ = sunset\n            else {\n                return false\n        }\n\n        var lsunrise, lsunset: Date\n        switch zenith {\n        case .strict:\n            lsunrise = strictSunrise!\n            lsunset = strictSunset!\n        case .civil:\n            lsunrise = civilSunrise!\n            lsunset = civilSunset!\n        case .nautical:\n            lsunrise = nauticalSunrise!\n            lsunset = nauticalSunset!\n        case .astronimical:\n            lsunrise = astronomicalSunrise!\n            lsunset = astronomicalSunset!\n        default:\n            lsunrise = sunrise!\n            lsunset = sunset!\n        }\n\n        let beginningOfDay = lsunrise.timeIntervalSince1970\n        let endOfDay = lsunset.timeIntervalSince1970\n        let currentTime = self.date.timeIntervalSince1970\n\n        let isSunriseOrLater = currentTime >= beginningOfDay\n        let isBeforeSunset = currentTime < endOfDay\n\n        return isSunriseOrLater && isBeforeSunset\n    }\n\n    public func getTimeSlice() -> String {\n        guard\n            let _ = sunrise,\n            let _ = sunset\n            else {\n                return \"\"\n        }\n\n        // We use\n        var lsunrise, lsunset: Date\n\n        if astronomicalSunset != nil && astronomicalSunrise != nil {\n            lsunrise = astronomicalSunrise!\n            lsunset = astronomicalSunset!\n        } else if nauticalSunset != nil && nauticalSunrise != nil {\n            lsunrise = nauticalSunrise!\n            lsunset = nauticalSunset!\n        } else if civilSunset != nil && civilSunrise != nil {\n            lsunrise = civilSunrise!\n            lsunset = civilSunset!\n        } else {\n            lsunrise = sunrise!\n            lsunset = sunset!\n        }\n\n        debugLog(\"lsunrise \\(lsunrise) lsunriseEnd \\(lsunrise.addingTimeInterval(TimeInterval(PrefsTime.sunEventWindow)))\")\n        debugLog(\"psunset \\(lsunset.addingTimeInterval(TimeInterval(-PrefsTime.sunEventWindow))) lsunset \\(lsunset)\")\n        debugLog(\"current \\(self.date)\")\n\n        if self.date < lsunrise || self.date > lsunset {\n            // So this is night, before sunrise, after sunset\n            debugLog(\"night\")\n            return \"night\"\n        } else if self.date > lsunrise && self.date < lsunrise.addingTimeInterval(TimeInterval(PrefsTime.sunEventWindow)) {\n            // Sunrise-period is a 3hr period after astro sunrise\n            debugLog(\"sunrise\")\n            return \"sunrise\"\n        } else if self.date > lsunset.addingTimeInterval(TimeInterval(-PrefsTime.sunEventWindow)) && self.date < lsunset {\n            // Sunset-period is a 3hr period prior astro sunset\n            debugLog(\"sunset\")\n            return \"sunset\"\n        } else {\n            // Let's say this is day\n            debugLog(\"day\")\n            return \"day\"\n        }\n    }\n}\n\n// MARK: - Helper extensions\n\nprivate extension Double {\n    var degreesToRadians: Double {\n        return Double(self) * (Double.pi / 180.0)\n    }\n\n    var radiansToDegrees: Double {\n        return (Double(self) * 180.0) / Double.pi\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Models/Time/TimeManagement.swift",
    "content": "//\n//  TimeManagement.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 05/10/2018.\n//  Copyright © 2018 John Coates. All rights reserved.\n//\n\nimport Foundation\nimport Cocoa\nimport CoreLocation\nimport IOKit.ps\n\n// swiftlint:disable:next type_body_length\nfinal class TimeManagement: NSObject {\n    static let sharedInstance = TimeManagement()\n\n    var solar: Solar?\n    var lsLatitude: Double?\n    var lsLongitude: Double?\n\n    // MARK: - Lifecycle\n    override init() {\n        super.init()\n        debugLog(\"Time Management initialized\")\n        if PrefsTime.timeMode == .locationService {\n            // This is racy... I think we're ok because time/location gets inited first, but still...\n            let location = Locations.sharedInstance\n\n            location.getCoordinates(failure: { (_) in\n                errorLog(\"Location services denied access to your location. Please make sure you allowed ScreenSaverEngine, Aerial, or legacyScreenSaver to access your location in System Preferences > Security and Privacy > Privacy\")\n            }, success: { (coordinates) in\n                self.lsLatitude = coordinates.latitude\n                self.lsLongitude = coordinates.longitude\n                debugLog(\"Location found \\(self.lsLatitude ?? 0) \\(self.lsLongitude ?? 0)\")\n                _ = self.calculateFrom(latitude: self.lsLatitude!, longitude: self.lsLongitude!)\n            })\n        } else {\n            _ = calculateFromCoordinates()\n        }\n    }\n\n    // MARK: - What should we play ?\n    // swiftlint:disable:next cyclomatic_complexity\n    func shouldRestrictPlaybackToDayNightVideo() -> (Bool, String) {\n        debugLog(\"PrefsTime : \\(PrefsTime.timeMode)\")\n        // We override everything on dark mode if we need to\n        if PrefsTime.darkModeNightOverride && DarkMode.isEnabled() {\n            debugLog(\"Dark Mode override\")\n            return (true, \"night\")\n        }\n\n        // If not we check the modes\n        if PrefsTime.timeMode == .locationService {\n            if let lat = lsLatitude, let lon = lsLongitude {\n                _ = calculateFrom(latitude: lat, longitude: lon)\n\n                if solar != nil {\n                    debugLog(\"Location service : \\(solar!.getTimeSlice())\")\n                    return (true, solar!.getTimeSlice())\n                }\n            } else {\n                debugLog(\"No location available, failing timeMode\")\n            }\n\n            return (false, \"\")\n        } else if PrefsTime.timeMode == .lightDarkMode {\n            debugLog(\"Light/dark : \\(DarkMode.isEnabled() ? \"night\" : \"day\")\")\n            return (true, DarkMode.isEnabled() ? \"night\" : \"day\")\n        } else if PrefsTime.timeMode == .coordinates {\n            _ = calculateFromCoordinates()\n\n            if solar != nil {\n                debugLog(\"Coordinates : \\(solar!.getTimeSlice())\")\n                return (true, solar!.getTimeSlice())\n            } else {\n                errorLog(\"You need to input latitude and longitude for calculations to work\")\n                return (false, \"\")\n            }\n        } else if PrefsTime.timeMode == .nightShift {\n            let (isNSCapable, sunrise, sunset, _) = NightShift.getInformation()\n            if !isNSCapable {\n                errorLog(\"Trying to use Night Shift on a non capable Mac\")\n                return (false, \"\")\n            }\n\n            debugLog(\"Night shift : \\(dayNightCheck(sunrise: sunrise!, sunset: sunset!))\")\n            return (true, dayNightCheck(sunrise: sunrise!, sunset: sunset!))\n        } else if PrefsTime.timeMode == .manual {\n            // We get the manual values from our preferences, as string, and convert them to dates\n            let dateFormatter = DateFormatter()\n            dateFormatter.dateFormat = \"HH:mm\"\n\n            guard let dateSunrise = dateFormatter.date(from: PrefsTime.manualSunrise) else {\n                errorLog(\"Invalid sunrise time in preferences\")\n                return(false, \"\")\n            }\n            guard let dateSunset = dateFormatter.date(from: PrefsTime.manualSunset) else {\n                errorLog(\"Invalid sunset time in preferences\")\n                return(false, \"\")\n            }\n\n            debugLog(\"Manual : \\(dayNightCheck(sunrise: dateSunrise, sunset: dateSunset))\")\n            return (true, dayNightCheck(sunrise: dateSunrise, sunset: dateSunset))\n        }\n\n        // default is show anything\n        return (false, \"\")\n    }\n\n    public func getSunriseSunset() -> (Date?, Date?) {\n        switch PrefsTime.timeMode {\n        case .disabled:\n            return (nil, nil)\n        case .nightShift:\n            let (_, sunrise, sunset, _) = NightShift.getInformation()\n            return (sunrise, sunset)\n        case .manual:\n            let dateFormatter = DateFormatter()\n            dateFormatter.dateFormat = \"HH:mm\"\n\n            guard let dateSunrise = dateFormatter.date(from: PrefsTime.manualSunrise) else {\n                errorLog(\"Invalid sunrise time in preferences\")\n                return(nil, nil)\n            }\n            guard let dateSunset = dateFormatter.date(from: PrefsTime.manualSunset) else {\n                errorLog(\"Invalid sunset time in preferences\")\n                return(nil, nil)\n            }\n            return (dateSunrise, dateSunset)\n        case .lightDarkMode:\n            return (nil, nil)\n        case .coordinates:\n            return (nil, nil)\n        case .locationService:\n            if let lat = lsLatitude, let lon = lsLongitude {\n                _ = calculateFrom(latitude: lat, longitude: lon)\n\n                return (solar?.astronomicalSunrise, solar?.astronomicalSunset)\n            }\n            return(nil, nil)\n        }\n    }\n\n    // Get the correct Zenith value for our pref\n    private func getZenith(_ mode: SolarMode) -> Solar.Zenith {\n        switch mode {\n        case .strict:\n            return .strict\n        case .official:\n            return .official\n        case .civil:\n            return .civil\n        case .nautical:\n            return .nautical\n        default:\n            return .astronimical\n        }\n    }\n\n    // Check if we are at day or night based on provided sunrise and sunset dates\n    private func dayNightCheck(sunrise: Date, sunset: Date) -> String {\n        var nsunrise = sunrise\n        var nsunset = sunset\n        let now = Date()\n        // When used with manual mode, sunrise and sunset will always be set to 2000-01-01\n        // With night mode, sunrise and sunset are the \"current\" ones (if at 23:00, sunset = today, sunrise = tomorrow)\n        // That may not always be true though, if you mess with your system clock (go back in time), both values\n        // can be in the future (and possibly in the past)\n        //\n        // As a sanity check, we check if we are between a sunset and a sunrise (prefered calculation mode with night\n        // shift as it takes into account everything correctly for us), if not we todayize the dates. In manual mode,\n        // will always be todayized\n        if (now < sunrise && now < sunset) || (now > sunrise && now > sunset) {\n            nsunrise = todayizeDate(date: sunrise)!\n            nsunset = todayizeDate(date: sunset)!\n        }\n\n        if now < nsunrise || now > nsunset {\n            // So this is night, before sunrise, after sunset\n            debugLog(\"night\")\n            return \"night\"\n        } else if now > nsunrise && now < nsunrise.addingTimeInterval(TimeInterval(PrefsTime.sunEventWindow)) {\n            // Sunrise-period is a 3hr period after astro sunrise\n            debugLog(\"sunrise\")\n            return \"sunrise\"\n        } else if now > nsunset.addingTimeInterval(TimeInterval(-PrefsTime.sunEventWindow)) && now < nsunset {\n            // Sunset-period is a 3hr period prior astro sunset\n            debugLog(\"sunset\")\n            return \"sunset\"\n        } else {\n            // Let's say this is day\n            debugLog(\"day\")\n            return \"day\"\n        }\n    }\n\n    // Change a date's day to today\n    private func todayizeDate(date: Date) -> Date? {\n        // Get today's date as a string\n        let dateFormatter = DateFormatter()\n        let current = Date()\n        dateFormatter.dateFormat = \"yyyy-MM-dd\"\n        let today = dateFormatter.string(from: current)\n\n        // Extract hour from date\n        dateFormatter.dateFormat = \"HH:mm:ss +zzzz\"\n        let format = today + \" \" + dateFormatter.string(from: date)\n\n        // Now return the todayized string\n        dateFormatter.dateFormat = \"yyyy-MM-dd HH:mm:ss +zzzz\"\n        if let newdate = dateFormatter.date(from: format) {\n            return newdate\n        } else {\n            return nil\n        }\n    }\n\n    // MARK: Calculate using Solar\n    func calculateFromCoordinates() -> (Bool, String) {\n        if PrefsTime.timeMode == .locationService {\n            // This is racy... I think we're ok because time/location gets inited first, but still...\n            let location = Locations.sharedInstance\n\n            location.getCoordinates(failure: { (_) in\n                errorLog(\"Location services denied access to your location. Please make sure you allowed ScreenSaverEngine, Aerial, or legacyScreenSaver to access your location in System Preferences > Security and Privacy > Privacy\")\n            }, success: { (coordinates) in\n                self.lsLatitude = coordinates.latitude\n                self.lsLongitude = coordinates.longitude\n                _ = self.calculateFrom(latitude: self.lsLatitude!, longitude: self.lsLongitude!)\n            })\n        } else {\n            if PrefsTime.latitude != \"\" && PrefsTime.longitude != \"\" {\n                return calculateFrom(latitude: Double(PrefsTime.latitude) ?? 0, longitude: Double(PrefsTime.longitude) ?? 0)\n            }\n        }\n\n        return (false, \"Can't process your coordinates, please verify\")\n    }\n\n    private func calculateFrom(latitude: Double, longitude: Double) -> (Bool, String) {\n        solar = Solar.init(coordinate: CLLocationCoordinate2D(\n            latitude: latitude,\n            longitude: longitude))\n\n        if solar != nil {\n            let dateFormatter = DateFormatter()\n            dateFormatter.dateFormat = DateFormatter.dateFormat(fromTemplate: \"j:mm:ss\", options: 0, locale: Locale.current)\n\n            let (sunrise, sunset) = getSunriseSunsetForMode(PrefsTime.solarMode)\n\n            if sunrise == nil || sunset == nil {\n               return (false, \"Can't process your coordinates, please verify\")\n            }\n\n            let sunriseString = dateFormatter.string(from: sunrise!)\n            let sunsetString = dateFormatter.string(from: sunset!)\n\n            if PrefsTime.solarMode == .official || PrefsTime.solarMode == .strict {\n                return(true, \"Today’s sunrise: \" + sunriseString + \"  Today’s sunset: \" + sunsetString)\n            } else {\n                return(true, \"Today’s dawn: \" + sunriseString + \"  Today’s dusk: \" + sunsetString)\n            }\n        }\n\n        return (false, \"Can't process your coordinates, please verify\")\n    }\n\n    // Helper to get the correct sunrise/sunset\n    func getSunriseSunsetForMode(_ mode: SolarMode) -> (Date?, Date?) {\n        if let sol = solar {\n            switch mode {\n            case .official:\n                return (sol.sunrise, sol.sunset)\n            case .strict:\n                return (sol.strictSunrise, sol.strictSunset)\n            case .civil:\n                return (sol.civilSunrise, sol.civilSunset)\n            case .nautical:\n                return (sol.nauticalSunrise, sol.nauticalSunset)\n            default:\n                return (sol.astronomicalSunrise, sol.astronomicalSunset)\n            }\n        }\n\n        return (nil, nil)\n    }\n\n    // MARK: - Brightness stuff (early, may get moved/will change)\n    func getCurrentSleepTime() -> Int {\n        // pmset -g | grep \"^[ ]*sleep\" | awk '{ print $2 }'\n\n        let pipe1 = Pipe()\n        let pmset = Process()\n        pmset.launchPath = \"/usr/bin/env\"\n        pmset.arguments = [\"pmset\", \"-g\"]\n        pmset.standardOutput = pipe1\n\n        let pipe2 = Pipe()\n        let grep = Process()\n        grep.launchPath = \"/usr/bin/env\"\n        grep.arguments = [\"grep\", \"^[ ]*sleep\"]\n        grep.standardInput = pipe1\n        grep.standardOutput = pipe2\n\n        let pipeOut = Pipe()\n        let awk = Process()\n        awk.launchPath = \"/usr/bin/env\"\n        awk.arguments = [\"awk\", \"{ print $2 }\"]\n        awk.standardInput = pipe2\n        awk.standardOutput = pipeOut\n        awk.standardOutput = pipeOut\n\n        pmset.launch()\n        grep.launch()\n        awk.launch()\n        awk.waitUntilExit()\n\n        let data = pipeOut.fileHandleForReading.readDataToEndOfFile()\n        let output = String(data: data, encoding: .utf8)\n\n        if output != nil {\n            let lines = output!.split(separator: \"\\n\")\n            if lines.count == 1 {\n                let newline = Int(lines[0])\n                if let newLineIndex = newline {\n                    return newLineIndex\n                }\n            }\n        }\n\n        return 0\n    }\n/*\n    // MARK: - Location detection\n    func startLocationDetection() {\n        let locationManager = CLLocationManager()\n        locationManager.delegate = self\n\n        if CLLocationManager.locationServicesEnabled() {\n            debugLog(\"Location services enabled\")\n            locationManager.startUpdatingLocation()\n        } else {\n            errorLog(\"Location services are disabled, please check your macOS settings!\")\n        }\n\n        if #available(OSX 10.14, *) {\n            locationManager.requestLocation()\n        } else {\n            // Fallback on earlier versions\n        }\n    }*/\n\n}\n/*\n// MARK: - Core Location Delegates\nextension TimeManagement: CLLocationManagerDelegate {\n    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {\n        _ = locations[locations.count - 1]\n    }\n\n    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {\n        errorLog(\"Location Manager error : \\(error)\")\n    }\n}*/\n"
  },
  {
    "path": "Aerial/Source/Views/AerialPlayerItem.swift",
    "content": "//\n//  AerialPlayerItem.swift\n//  Aerial\n//\n//  Created by Ethan Setnik on 11/22/17.\n//  Copyright © 2017 John Coates. All rights reserved.\n//\nimport AVFoundation\nimport AVKit\n\nfinal class AerialPlayerItem: AVPlayerItem {\n    var video: AerialVideo?\n\n    init(video: AerialVideo) {\n        let videoURL = video.url\n        let asset = cachedOrCachingAsset(videoURL)\n        super.init(asset: asset, automaticallyLoadedAssetKeys: nil)\n        self.video = video\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Views/AerialView+Brightness.swift",
    "content": "//\n//  AerialView+Brightness.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 06/12/2019.\n//  Copyright © 2019 Guillaume Louel. All rights reserved.\n//\n\nimport Foundation\n\nextension AerialView {\n    // We make sure we should dim, we're not a preview, we haven't dimmed yet (multi monitor)\n    // and ensure we properly apply the night/battery restrictions !\n    func checkIfShouldSetBrightness() {\n        \n        let timeManagement = TimeManagement.sharedInstance\n\n        if PrefsDisplays.dimBrightness && !isPreview && brightnessToRestore == nil {\n            let (should, to) = timeManagement.shouldRestrictPlaybackToDayNightVideo()\n\n            if !PrefsDisplays.dimOnlyAtNight || (PrefsDisplays.dimOnlyAtNight && should && to == \"night\") {\n                if !PrefsDisplays.dimOnlyOnBattery || (PrefsDisplays.dimOnlyOnBattery && Battery.isUnplugged()) {\n                    brightnessToRestore = Brightness.get()\n                    // brightnessToRestore = timeManagement.getBrightness()\n                    debugLog(\"Brightness before Aerial was launched : \\(String(describing: brightnessToRestore))\")\n                    Brightness.set(level: min(Float(PrefsDisplays.startDim), brightnessToRestore!))\n                    setDimTimers()\n                }\n            }\n        }\n    }\n\n    // Set the timers to progressively dim the screen brightness (in 10 steps)\n    // Currently, this only works with internal monitors\n    func setDimTimers() {\n        if #available(OSX 10.12, *) {\n            let timeManagement = TimeManagement.sharedInstance\n            let startValue = min(PrefsDisplays.startDim, Double(brightnessToRestore!))\n\n            if PrefsDisplays.dimBrightness && startValue > PrefsDisplays.endDim {\n                debugLog(\"setting brightness timers from \\(String(describing: startValue)) to \\(String(describing: PrefsDisplays.endDim))\")\n                var interval: Int\n                if PrefsDisplays.overrideDimInMinutes {\n                    interval = PrefsDisplays.dimInMinutes * 6 // * 60 / 10, we make 10 intermediate steps\n                } else {\n                    interval = timeManagement.getCurrentSleepTime() * 6\n                    if interval == 0 {\n                        interval = 180 // Fallback to 30 mins if no sleep\n                    }\n                }\n                debugLog(\"Step size: \\(interval) seconds\")\n\n                for idx in 1...10 {\n                    _ = Timer.scheduledTimer(withTimeInterval: TimeInterval(interval * idx), repeats: false) { (_) in\n                        let val = startValue - ((startValue - PrefsDisplays.endDim) / 10 * Double(idx))\n                        debugLog(\"Firing event \\(idx) brightness to \\(val)\")\n                        Brightness.set(level: Float(val))\n                    }\n                }\n            }\n        } else {\n            // Fallback on earlier versions\n            warnLog(\"Brightness control not available < macOS 10.12\")\n        }\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Views/AerialView+Player.swift",
    "content": "//\n//  AerialView+Player.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 06/12/2019.\n//  Copyright © 2019 Guillaume Louel. All rights reserved.\n//\n\nimport Foundation\nimport AVFoundation\nimport AVKit\n\nextension AerialView {\n    func setupPlayerLayer(withPlayer player: AVPlayer) {\n        let displayDetection = DisplayDetection.sharedInstance\n\n        self.layer = CALayer()\n        guard let layer = self.layer else {\n            errorLog(\"\\(self.description) Couldn't create CALayer\")\n            return\n        }\n        self.wantsLayer = true\n        layer.backgroundColor = NSColor.black.cgColor\n        layer.needsDisplayOnBoundsChange = true\n        layer.frame = self.bounds\n        debugLog(\"\\(self.description) setting up player layer with bounds/frame: \\(layer.bounds) / \\(layer.frame)\")\n\n        playerLayer = AVPlayerLayer(player: player)\n\n        // Fill/fit is only available in 10.10+\n        if #available(OSX 10.10, *) {\n            if PrefsDisplays.aspectMode == .fill {\n                playerLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill\n            } else {\n                playerLayer.videoGravity = AVLayerVideoGravity.resizeAspect\n            }\n        }\n        playerLayer.autoresizingMask = [CAAutoresizingMask.layerWidthSizable, CAAutoresizingMask.layerHeightSizable]\n\n        // In case of span mode we need to compute the size of our layer\n        if PrefsDisplays.viewingMode == .spanned && !isPreview {\n            let zRect = displayDetection.getZeroedActiveSpannedRect()\n            debugLog(\"foundScreen check : \\(foundScreen.debugDescription)\")\n            \n            if let scr = foundScreen {\n                let tRect = CGRect(x: zRect.origin.x - scr.zeroedOrigin.x,\n                                   y: zRect.origin.y - scr.zeroedOrigin.y,\n                                   width: zRect.width,\n                                   height: zRect.height)\n                debugLog(\"tRect : \\(tRect)\")\n                playerLayer.frame = tRect\n            } else {\n                debugLog(\"This is an unknown screen in span mode, workarounding...\")\n                \n                if let alternateScreen = DisplayDetection.sharedInstance.alternateFindScreenWith(frame: self.frame) {\n                    foundScreen = alternateScreen\n                    debugLog(\"📺 alternate screen found : \\(alternateScreen.description)\")\n                    let tRect = CGRect(x: zRect.origin.x - alternateScreen.zeroedOrigin.x,\n                                       y: zRect.origin.y - alternateScreen.zeroedOrigin.y,\n                                       width: zRect.width,\n                                       height: zRect.height)\n                    playerLayer.frame = tRect\n                } else {\n                    errorLog(\"No alternate screen found, reverting to single screen mode\")\n                    playerLayer.frame = layer.bounds\n                }\n            }\n        } else {\n            playerLayer.frame = layer.bounds\n\n            // \"true\" mirrored mode\n            let index = AerialView.instanciatedViews.firstIndex(of: self) ?? 0\n            if index % 2 == 1 && PrefsDisplays.viewingMode == .mirrored {\n                playerLayer.transform = CATransform3DMakeAffineTransform(CGAffineTransform(scaleX: -1, y: 1))\n            }\n        }\n        layer.addSublayer(playerLayer)\n\n        layer.contentsScale = (self.window?.backingScaleFactor) ?? 1.0\n        self.playerLayer.contentsScale = (self.window?.backingScaleFactor) ?? 1.0\n\n        \n        // The layers for descriptions, clock, message\n        // On Sonoma we can't use the reported frame!\n        if foundFrame != nil {\n            layerManager.setupExtraLayers(layer: layer, frame: foundFrame!)\n        } else {\n            layerManager.setupExtraLayers(layer: layer, frame: self.frame)\n        }\n        // Make sure we set the retinaness here\n        layerManager.setContentScale(scale: self.window?.backingScaleFactor ?? 1.0)\n\n        // An extra layer to try and contravent a macOS graphics driver bug\n        // This is useful on High Sierra+ on Intel Macs\n        if #available(macOS 12.0, *) {\n        } else {\n            setupGlitchWorkaroundLayer(layer: layer)\n        }\n   }\n\n    // MARK: - AVPlayerItem Notifications\n\n    @objc func playerItemFailedtoPlayToEnd(_ aNotification: Notification) {\n        warnLog(\"\\(self.description) AVPlayerItemFailedToPlayToEndTimeNotification \\(aNotification)\")\n        playNextVideo()\n    }\n\n    @objc func playerItemNewErrorLogEntryNotification(_ aNotification: Notification) {\n        warnLog(\"\\(self.description) AVPlayerItemNewErrorLogEntryNotification \\(aNotification)\")\n    }\n\n    @objc func playerItemPlaybackStalledNotification(_ aNotification: Notification) {\n        warnLog(\"\\(self.description) AVPlayerItemPlaybackStalledNotification \\(aNotification)\")\n    }\n\n    @objc func playerItemDidReachEnd(_ aNotification: Notification) {\n        debugLog(\"\\(self.description) played did reach end\")\n        debugLog(\"\\(self.description) notification: \\(aNotification)\")\n\n        if shouldLoop {\n            debugLog(\"Rewinding video!\")\n            if let playerItem = aNotification.object as? AVPlayerItem {\n                playerItem.seek(to: CMTime.zero, completionHandler: nil)\n            }\n        } else {\n            playNextVideo()\n            debugLog(\"\\(self.description) playing next video for player \\(String(describing: player))\")\n        }\n\n    }\n\n    // Video fade-in/out\n    func addPlayerFades(view: AerialView, player: AVPlayer, video: AerialVideo) {\n        if !Aerial.helper.underCompanion {\n            // We only fade in/out if we have duration\n            if video.duration > 0 && AerialView.shouldFade && !shouldLoop {\n                let playbackSpeed = Double(PlaybackSpeed.forVideo(video.id))\n\n                view.playerLayer.opacity = 0\n                let fadeAnimation = CAKeyframeAnimation(keyPath: \"opacity\")\n                fadeAnimation.values = [0, 1, 1, 0] as [Int]\n                fadeAnimation.keyTimes = [0,\n                                          AerialView.fadeDuration/(video.duration/playbackSpeed),\n                                          1-(AerialView.fadeDuration/(video.duration/playbackSpeed)), 1 ] as [NSNumber]\n\n                fadeAnimation.duration = video.duration/playbackSpeed\n                if #available(macOS 10.14, *) {\n                    fadeAnimation.calculationMode = CAAnimationCalculationMode.cubic\n                } else {\n                    // Fallback on earlier versions\n                }\n                view.playerLayer.add(fadeAnimation, forKey: \"mainfade\")\n            } else {\n                view.playerLayer.opacity = 1.0\n            }\n        } else {\n            view.playerLayer.opacity = 1.0\n        }\n    }\n\n    func removePlayerFades() {\n        self.playerLayer.removeAllAnimations()\n        self.playerLayer.opacity = 1.0\n    }\n    \n    // This works pre Catalina as of right now\n    func setupGlitchWorkaroundLayer(layer: CALayer) {\n        debugLog(\"Using dot workaround for video driver corruption\")\n\n        let workaroundLayer = CATextLayer()\n        workaroundLayer.frame = self.bounds\n        workaroundLayer.opacity = 1.0\n        workaroundLayer.font = NSFont(name: \"Helvetica Neue Medium\", size: 4)\n        workaroundLayer.fontSize = 4\n        workaroundLayer.string = \".\"\n\n        let attributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.font: workaroundLayer.font as Any]\n\n        // Calculate bounding box\n        let attrString = NSAttributedString(string: workaroundLayer.string as! String, attributes: attributes)\n        let rect = attrString.boundingRect(with: layer.visibleRect.size, options: NSString.DrawingOptions.usesLineFragmentOrigin)\n\n        workaroundLayer.frame = rect\n        workaroundLayer.position = CGPoint(x: 2, y: 2)\n        workaroundLayer.anchorPoint = CGPoint(x: 0, y: 0)\n        layer.addSublayer(workaroundLayer)\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Views/AerialView.swift",
    "content": "//\n//  AerialView.swift\n//  Aerial\n//\n//  Created by John Coates on 10/22/15.\n//  Copyright © 2015 John Coates. All rights reserved.\n//\n\nimport Foundation\nimport ScreenSaver\nimport AVFoundation\nimport AVKit\n\n@objc(AerialView)\n// swiftlint:disable:next type_body_length\nfinal class AerialView: ScreenSaverView, CAAnimationDelegate {\n    var layerManager: LayerManager\n    var playerLayer: AVPlayerLayer!\n\n    static var players: [AVPlayer] = [AVPlayer]()\n    static var previewPlayer: AVPlayer?\n    static var previewView: AerialView?\n\n    var player: AVPlayer?\n    var currentVideo: AerialVideo?\n\n    var preferencesController: PanelWindowController?\n\n    var observerWasSet = false\n    var hasStartedPlaying = false\n    var wasStopped = false\n    var isDisabled = false\n\n    var isQuickFading = false\n\n    var brightnessToRestore: Float?\n\n    var globalSpeed: Float = 1.0\n    var globalPause = false\n\n    // We use this for tentative Catalina bug workaround\n    var originalWidth, originalHeight: CGFloat\n\n    // We use this for tentative Sonoma bug workaround\n    var foundScreen: Screen?\n    var foundFrame: NSRect?\n\n    // Tentative improvement when only one video in playlist\n    var shouldLoop = false\n\n    static var shouldFade: Bool {\n        return (PrefsVideos.fadeMode != .disabled)\n    }\n\n    static var fadeDuration: Double {\n        switch PrefsVideos.fadeMode {\n        case .t0_5:\n            return 0.5\n        case .t1:\n            return 1\n        case .t2:\n            return 2\n        default:\n            return 0.10\n        }\n    }\n\n    static var textFadeDuration: Double {\n        switch PrefsInfo.fadeModeText {\n        case .t0_5:\n            return 0.5\n        case .t1:\n            return 1\n        case .t2:\n            return 2\n        default:\n            return 0.10\n        }\n    }\n\n    // Mirrored/cloned viewing mode and Spanned viewing mode share the same player for sync & ressource saving\n    static var sharingPlayers: Bool {\n        switch PrefsDisplays.viewingMode {\n        case .cloned, .mirrored, .spanned:\n            return true\n        default:\n            return false\n        }\n    }\n\n    static var sharedViews: [AerialView] = []\n    // Because of lifecycle in Preview, we may pile up old/no longer\n    // shared instanciated views that we need to track to not reuse\n    static var instanciatedViews: [AerialView] = []\n\n    // MARK: - Shared Player\n    static var singlePlayerAlreadySetup: Bool = false\n    static var sharedPlayerIndex: Int?\n    static var didSkipMain: Bool = false\n\n    class var sharedPlayer: AVPlayer {\n        struct Static {\n            static let instance: AVPlayer = AVPlayer()\n            // swiftlint:disable:next identifier_name\n            static var _player: AVPlayer?\n            static var player: AVPlayer {\n                if let activePlayer = _player {\n                    return activePlayer\n                }\n\n                _player = AVPlayer()\n                return _player!\n            }\n        }\n\n        return Static.player\n    }\n\n    // MARK: - Init / Setup\n    // This is the one used by System Preferences/ScreenSaverEngine\n    override init?(frame: NSRect, isPreview: Bool) {\n        Aerial.helper.checkCompanion()\n\n        // Clear log if > 1MB on startup\n        rollLogIfNeeded()\n\n        // Set Companion bridge notifications under Sonoma, but not under Companion\n        if !Aerial.helper.underCompanion {\n            if #available(macOS 14, *) {\n                CompanionBridge.setNotifications()\n            }\n        }\n        \n        // legacyScreenSaver always return true for isPreview on Catalina\n        // We need to detect and override ourselves\n        // This is finally fixed in Ventura\n        var preview = false\n        self.originalWidth = frame.width\n        self.originalHeight = frame.height\n\n        if frame.width < 400 && frame.height < 300 {\n            preview = true\n        }\n        \n        // This is where we manage our location info layers, clock, etc\n        self.layerManager = LayerManager(isPreview: preview)\n\n        super.init(frame: frame, isPreview: preview)\n        debugLog(\"🖼️ AVinit (.saver) \\(frame) p: \\(isPreview) o: \\(preview)\")\n\n        self.animationTimeInterval = 1.0 / 30.0\n\n        if Aerial.helper.underCompanion && isPreview {\n            debugLog(\"Running under companion in preview mode, preventing setup\")\n        } else {\n            // We need to delay things under Sonoma because legacyScreenSaver is awesome\n            if #available(macOS 14.0, *) {\n                var delay = 0.01\n                \n                // If nightshift we delay more\n                if !Aerial.helper.underCompanion && PrefsTime.timeMode == .nightShift {\n                    delay = 0.5\n                }\n\n                DispatchQueue.main.asyncAfter(deadline: .now() + delay) {\n                    debugLog(\"🖼️ AVinit delayed setup!\")\n                    self.setup()\n                }\n            } else {\n                setup()\n            }\n        }\n    }\n\n    // This is the one used by our App target used for debugging\n    required init?(coder: NSCoder) {\n        Aerial.helper.appMode = true\n\n        Aerial.helper.checkCompanion()\n\n        // Clear log if > 1MB on startup\n        rollLogIfNeeded()\n\n        // Set Companion bridge notifications under Sonoma, but not under Companion\n        if !Aerial.helper.underCompanion {\n            if #available(macOS 14, *) {\n                CompanionBridge.setNotifications()\n            }\n        }\n\n        \n        self.layerManager = LayerManager(isPreview: false)\n\n        // ...\n        self.originalWidth = 0\n        self.originalHeight = 0\n\n        super.init(coder: coder)\n        self.originalWidth = frame.width\n        self.originalHeight = frame.height\n\n        debugLog(\"🖼️ AVinit .app\")\n        \n        // We need to delay things under Sonoma because legacyScreenSaver is awesome\n        if #available(macOS 14.0, *) {\n            DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {\n                debugLog(\"🖼️ AVinit delayed setup!\")\n                self.setup()\n            }\n        } else {\n            setup()\n        }\n    }\n\n    deinit {\n        Aerial.helper.maybeUnmuteSound()\n        \n        debugLog(\"🖼️ \\(self.description) AVdeinit \")\n        NotificationCenter.default.removeObserver(self)\n    }\n\n    func ensureCorrectFormat() {\n        if #available(OSX 10.15, *) {\n        } else {\n            // No HDR allowed here\n            if PrefsVideos.videoFormat == .v4KHDR {\n                debugLog(\"🖼️⚠️ Fixing 4K HDR not allowed prior to Catalina\")\n                PrefsVideos.videoFormat = .v4KHEVC\n            } else if PrefsVideos.videoFormat == .v1080pHDR {\n                debugLog(\"🖼️⚠️ Fixing 1080p HDR not allowed prior to Catalina\")\n                PrefsVideos.videoFormat = .v1080pHEVC\n            }\n        }\n    }\n\n    // swiftlint:disable:next cyclomatic_complexity\n    func setup() {\n        // Disable HDR only on macOS Ventura\n        if !Aerial.helper.canHDR() {\n            if isPreview && (PrefsVideos.videoFormat == .v4KHDR || PrefsVideos.videoFormat == .v1080pHDR) {\n                // This will lead to crashing in up to Ventura beta5 so disable\n                let debugTextView = NSTextView(frame: bounds.insetBy(dx: 20, dy: 20))\n                debugTextView.font = .labelFont(ofSize: 10)\n                debugTextView.string += \"HDR Previews hidden on Ventura\"\n                isDisabled = true\n                \n                self.addSubview(debugTextView)\n                return\n            }\n        }\n\n\n        \n        \n        // First we check the system appearance, as it relies on our view\n        Aerial.helper.computeDarkMode(view: self)\n\n        // Then check if we need to mute/unmute sound\n        Aerial.helper.maybeMuteSound()\n\n        // Kick up the timezone detection\n        _ = TimeManagement.sharedInstance\n\n        // This is to make sure we don't start in a format that's unsupported\n        ensureCorrectFormat()\n        \n        if let version = Bundle(identifier: \"com.JohnCoates.Aerial\")?.infoDictionary?[\"CFBundleShortVersionString\"] as? String {\n            debugLog(\"🖼️ \\(self.description) AV setup init (V\\(version)) preview: \\(self.isPreview)\")\n            debugLog(\"🖼️ Running \\(ProcessInfo.processInfo.operatingSystemVersionString)\")\n        }\n\n        // First thing, we may need to migrate the cache !\n        Cache.migrate()\n\n        // Now we need to check if we should remove lingering stuff from the cache !\n        if Cache.canNetwork() {\n            Cache.removeCruft()\n        }\n\n        // Check early if we need to enable power saver mode,\n        // black screen with minimal brightness\n        if !isPreview {\n            if (PrefsVideos.onBatteryMode == .alwaysDisabled && Battery.isUnplugged())\n                || (PrefsVideos.onBatteryMode == .disableOnLow && Battery.isLow()) {\n                debugLog(\"🖼️ Engaging power saving mode\")\n                isDisabled = true\n                Brightness.set(level: 0.0)\n                return\n            }\n        }\n\n        // We may need to set timers to progressively dim the screen\n        checkIfShouldSetBrightness()\n\n        // Shared views can get stuck, we may need to clean them up here\n        cleanupSharedViews()\n\n        // We look for the screen in our detected list.\n        // In case of preview or unknown screen result will be nil\n        let displayDetection = DisplayDetection.sharedInstance\n\n        let screenCount = displayDetection.getScreenCount()\n        debugLog(\"🖼️ Real screen count : \\(screenCount)\")\n\n        var thisScreen: Screen? = nil\n        if #available(macOS 14.0, *) {\n            if foundScreen == nil {\n                debugLog(\"🖼️ missing foundScreen, workarounding \\(String(describing: self.window?.screen))\")\n                if let missingScreen = self.window?.screen {\n                    debugLog(\"🖼️ screen attached\")\n                    matchScreen(thisScreen: missingScreen)\n                } else {\n                    errorLog(\"🖼️ still missing screen\")\n                }\n            } else {\n                debugLog(\"🖼️ early foundScreen ok \\(String(describing: foundScreen))\")\n            }\n        } else {\n            thisScreen = displayDetection.findScreenWith(frame: self.frame)\n        }\n        \n        // We note the foundFrame as this is more accurate than the reported one! We need this for coordinates mapping\n        if let thisScreen = thisScreen {\n            foundFrame = thisScreen.bottomLeftFrame\n            foundScreen = thisScreen\n            debugLog(\"🖼️ Using : \\(String(describing: thisScreen))\")\n        }\n\n        for twindow in NSApplication.shared.windows {\n            debugLog(\"window : \\(twindow.debugDescription)\")\n        }\n        \n        var localPlayer: AVPlayer?\n        \n        // Is the current screen disabled by user ?\n        if !isPreview {\n            // If it's an unknown screen, we leave it enabled\n            if let screen = foundScreen {\n                if !displayDetection.isScreenActive(id: screen.id) {\n                    // Then we disable and exit\n                    debugLog(\"🖼️ This display is not active, disabling\")\n                    isDisabled = true\n                    return\n                } else {\n                    debugLog(\"Screen is active\")\n                }\n            }\n        } else {\n            AerialView.previewView = self\n        }\n\n        // Track which views are sharing the sharedPlayer\n        if AerialView.sharingPlayers {\n            AerialView.sharedViews.append(self)\n        }\n\n        // We track all instanciated views here, independand of their shared status\n        AerialView.instanciatedViews.append(self)\n\n        // Setup the AVPlayer\n        if AerialView.sharingPlayers {\n            localPlayer = AerialView.sharedPlayer\n        } else {\n            localPlayer = AVPlayer()\n        }\n\n        guard let player = localPlayer else {\n            errorLog(\"\\(self.description) Couldn't create AVPlayer!\")\n            return\n        }\n\n        self.player = player\n\n        if isPreview {\n            AerialView.previewPlayer = player\n        } else if !AerialView.sharingPlayers {\n            // add to player list\n            AerialView.players.append(player)\n        }\n        \n        setupPlayerLayer(withPlayer: player)\n\n        // In mirror mode we use the main instance player\n        if AerialView.sharingPlayers && AerialView.singlePlayerAlreadySetup {\n            if let index = AerialView.sharedPlayerIndex {\n                self.playerLayer.player = AerialView.instanciatedViews[index].player\n                self.playerLayer.opacity = 0\n                return\n            }\n        }\n\n        // We're never sharing the preview !\n        if !isPreview {\n            AerialView.singlePlayerAlreadySetup = true\n            AerialView.sharedPlayerIndex = AerialView.instanciatedViews.count-1\n        }\n\n        // So first we wait for our list to be ready\n        VideoList.instance.addCallback {\n            // Then we may need to delay things a bit if we haven't gathered the coordinates yet\n            if PrefsTime.timeMode == .locationService && Locations.sharedInstance.coordinates == nil {\n                debugLog(\"🖼️⚠️ No coordinates yet, delaying a bit...\")\n                DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(300)) {\n                    self.playNextVideo()\n                }\n            } else {\n                self.playNextVideo()\n            }\n        }\n    }\n    \n    \n    override func viewDidMoveToWindow() {\n        super.viewDidMoveToWindow()\n        if foundScreen == nil {\n            debugLog(\"🖼️ \\(self.description) viewDidMoveToWindow frame: \\(self.frame) window: \\(String(describing: self.window))\")\n            debugLog(self.window?.screen.debugDescription ?? \"Unknown\")\n            \n            if let thisScreen = self.window?.screen {\n                matchScreen(thisScreen: thisScreen)\n            } else {\n                // For some reason we may not have a screen here!\n                debugLog(\"🖼️ no screen attached, will try again later\")\n            }\n        } else {\n            debugLog(\"🖼️ wdmtw after we already have a screen, ignoring\")\n        }\n        \n    }\n\n    func matchScreen(thisScreen: NSScreen) {\n        let screenID = thisScreen.deviceDescription[NSDeviceDescriptionKey(\"NSScreenNumber\")] as! CGDirectDisplayID\n        \n        debugLog(screenID.description)\n        \n        foundScreen = DisplayDetection.sharedInstance.findScreenWith(id: screenID)\n        if let foundScreen = foundScreen {\n            foundFrame = foundScreen.bottomLeftFrame\n            if #available(macOS 14, *) {\n                self.frame = foundFrame!\n\n                // remove it from the list of unused screens\n                DisplayDetection.sharedInstance.markScreenAsUsed(id: screenID)\n            }\n        }\n\n        debugLog(\"🖼️🌾 Using : \\(String(describing: foundScreen))\")\n        debugLog(\"🥬🌾 window.screen \\(String(describing: self.window?.screen.debugDescription))\")\n        debugLog(\"🖼️🌾 self.frame : \\(String(describing: self.frame))\")\n    }\n    \n    // Handle window resize\n    override func viewDidEndLiveResize() {\n        layerManager.redrawAllCorners()\n    }\n    \n    override func viewDidChangeBackingProperties() {\n        debugLog(\"🖼️ \\(self.description) backing change \\((self.window?.backingScaleFactor) ?? 1.0) isDisabled: \\(isDisabled) frame: \\(self.frame) preview: \\(self.isPreview)\")\n\n        // Tentative workaround for a Catalina+ bug\n        if self.frame.width < 300 && !isPreview {\n            debugLog(\"🖼️☢️ Frame size bug, trying to override to \\(originalWidth)x\\(originalHeight)!\")\n            self.frame = CGRect(x: 0, y: 0, width: originalWidth, height: originalHeight)\n        }\n\n        if !isDisabled {\n            if let layer = layer, let window = self.window {\n                layer.contentsScale = (window.backingScaleFactor) ?? 1.0\n                self.playerLayer.contentsScale = (window.backingScaleFactor) ?? 1.0\n\n                // And our additional layers\n                layerManager.setContentScale(scale: (window.backingScaleFactor) ?? 1.0)\n            }\n        }\n    }\n\n    // On previews, it's possible that our shared player was stopped and is not reusable\n    func cleanupSharedViews() {\n        if AerialView.singlePlayerAlreadySetup {\n            if let index = AerialView.sharedPlayerIndex {\n                if AerialView.instanciatedViews[index].wasStopped {\n                    AerialView.singlePlayerAlreadySetup = false\n                    AerialView.sharedPlayerIndex = nil\n\n                    AerialView.instanciatedViews = [AerialView]()   // Clear the list of instanciated stuff\n                    AerialView.sharedViews = [AerialView]()         // And the list of sharedViews\n                }\n            }\n        }\n    }\n\n    // MARK: - Lifecycle stuff\n    override func startAnimation() {\n        super.startAnimation()\n        debugLog(\"🖼️ \\(self.description) startAnimation frame \\(self.frame) bounds \\(self.bounds)\")\n\n        if !isDisabled {\n            // Previews may be restarted, but our layer will get hidden (somehow) so show it back\n            if isPreview && player?.currentTime() != CMTime.zero {\n                debugLog(\"restarting playback\")\n                playerLayer.opacity = 1\n                player?.play()\n            }\n        }\n    }\n\n    override func stopAnimation() {\n        Aerial.helper.maybeUnmuteSound()\n\n        wasStopped = true\n        debugLog(\"🖼️ \\(self.description) stopAnimation\")\n        if !isDisabled {\n            player?.pause()\n            player?.rate = 0\n            layerManager.removeAllLayers()\n            playerLayer.removeAllAnimations()\n            player?.replaceCurrentItem(with: nil)\n\n            isDisabled = true\n        }\n\n        if PrefsDisplays.dimBrightness {\n            if !isPreview, let brightnessToRestore = brightnessToRestore {\n                Brightness.set(level: brightnessToRestore)\n                self.brightnessToRestore = nil\n            }\n        }\n        \n        \n        teardown()\n    }\n\n    func teardown() {\n        debugLog(\"🖼️ \\(self.description) teardown\")\n\n        // Remove notifications observer\n        debugLog(\"🖼️ \\(self.description) clear notif\")\n        //clearNotifications()  // tmptest\n        // Clear layer animations\n        debugLog(\"🖼️ \\(self.description) clear anims\")\n        clearAllLayerAnimations()\n\n        if let player = player {\n            // Remove from player index\n            let indexMaybe = AerialView.players.firstIndex(of: player)\n\n            guard let index = indexMaybe else {\n                return\n            }\n            AerialView.players.remove(at: index)\n        }\n        \n        // Remove any download\n        VideoManager.sharedInstance.cancelAll()\n       \n        debugLog(\"🖼️ end teardown, exiting\")\n    }\n    \n    // Wait for the player to be ready\n    // swiftlint:disable:next block_based_kvo\n    internal override func observeValue(forKeyPath keyPath: String?,\n                                        of object: Any?, change: [NSKeyValueChangeKey: Any]?,\n                                        context: UnsafeMutableRawPointer?) {\n        debugLog(\"🖼️ \\(description) observeValue \\(String(describing: keyPath)) \\(playerLayer.isReadyForDisplay)\")\n\n        if let player = player, let currentVideo = currentVideo, playerLayer.isReadyForDisplay {\n            player.play()\n            hasStartedPlaying = true\n\n            if Aerial.helper.underCompanion {\n                player.rate = globalSpeed\n            } else {\n                player.rate = PlaybackSpeed.forVideo(currentVideo.id)\n            }\n\n            debugLog(\"🖼️ start playback: \\(frame) \\(bounds) rate: \\(player.rate)\")\n            debugLog(\"🥬🥬 window2 \\(String(describing: window?.screen))\")\n            // If we share a player, we need to add the fades and the text to all the\n            // instanciated views using it (eg: in mirrored mode)\n            if AerialView.sharingPlayers {\n                for view in AerialView.sharedViews {\n                    self.addPlayerFades(view: view, player: player, video: currentVideo)\n                    \n                    if (Aerial.helper.underCompanion && PrefsInfo.hideUnderCompanion) {\n                        debugLog(\"🖼️ Disable overlays under Companion\")\n                    } else {\n                        view.layerManager.setupLayersForVideo(video: currentVideo, player: player)\n                    }\n                }\n            } else {\n                self.addPlayerFades(view: self, player: player, video: currentVideo)\n                if (Aerial.helper.underCompanion && PrefsInfo.hideUnderCompanion) {\n                    debugLog(\"🖼️ Disable overlays under Companion\")\n                } else {\n                    self.layerManager.setupLayersForVideo(video: currentVideo, player: player)\n                }\n            }\n        }\n    }\n\n    // Remove all the layer animations on all shared views\n    func clearAllLayerAnimations() {\n        // Clear everything\n        if let player = player {\n            layerManager.clearLayerAnimations(player: player)\n            for view in AerialView.sharedViews {\n                view.layerManager.clearLayerAnimations(player: player)\n            }\n        }\n    }\n\n    func clearNotifications() {\n        NotificationCenter.default.removeObserver(self)\n        DistributedNotificationCenter.default.removeObserver(self)\n    }\n    \n    func setNotifications(_ currentItem: AVPlayerItem) {\n        let notificationCenter = NotificationCenter.default\n\n        notificationCenter.addObserver(self,\n                                       selector: #selector(AerialView.playerItemDidReachEnd(_:)),\n                                       name: NSNotification.Name.AVPlayerItemDidPlayToEndTime,\n                                       object: currentItem)\n        notificationCenter.addObserver(self,\n                                       selector: #selector(AerialView.playerItemNewErrorLogEntryNotification(_:)),\n                                       name: NSNotification.Name.AVPlayerItemNewErrorLogEntry,\n                                       object: currentItem)\n        notificationCenter.addObserver(self,\n                                       selector: #selector(AerialView.playerItemFailedtoPlayToEnd(_:)),\n                                       name: NSNotification.Name.AVPlayerItemFailedToPlayToEndTime,\n                                       object: currentItem)\n        notificationCenter.addObserver(self,\n                                       selector: #selector(AerialView.playerItemPlaybackStalledNotification(_:)),\n                                       name: NSNotification.Name.AVPlayerItemPlaybackStalled,\n                                       object: currentItem)\n\n        NSWorkspace.shared.notificationCenter.addObserver(\n                self, selector: #selector(onSleepNote(note:)),\n                name: NSWorkspace.willSleepNotification, object: nil)\n\n        DistributedNotificationCenter.default.addObserver(self,\n            selector: #selector(AerialView.willStart(_:)),\n            name: Notification.Name(\"com.apple.screensaver.willstart\"), object: nil)\n        DistributedNotificationCenter.default.addObserver(self,\n            selector: #selector(AerialView.willStop(_:)),\n            name: Notification.Name(\"com.apple.screensaver.willstop\"), object: nil)\n        /*DistributedNotificationCenter.default.addObserver(self,\n            selector: #selector(AerialView.screenIsUnlocked(_:)),\n            name: Notification.Name(\"com.apple.screenIsUnlocked\"), object: nil)\n        */\n        Music.instance.setup()\n    }\n\n    func sendNotification(video: AerialVideo) {\n        DistributedNotificationCenter.default.post(name: Notification.Name(\"com.glouel.aerial.nextvideo\"), object: \"aerialtest : \" + video.name)\n    }\n\n    \n    @objc func willStart(_ aNotification: Notification) {\n        if Aerial.helper.underCompanion {\n            debugLog(\"🖼️ 📢📢📢 willStart\")\n            player?.pause()\n        }\n    }\n\n    @objc func screenIsUnlocked(_ aNotification: Notification) {\n        if #available(macOS 14.0, *) {\n            debugLog(\"🖼️ 📢📢📢 ☢️sonoma☢️ workaround screenIsUnlocked\")\n            if !Aerial.helper.underCompanion {\n                if let player = player {\n                    layerManager.removeAllLayers()\n                    player.pause()\n                }\n                self.stopAnimation()\n            } else {\n                if !globalPause {\n                    player?.play()\n                    player?.rate = globalSpeed\n                }\n            }\n        }\n    }\n    \n    @objc func onSleepNote(note: Notification) {\n        debugLog(\"🖼️ 📢📢📢 onSleepNote\")\n        if !Aerial.helper.underCompanion {\n            if #available(macOS 14.0, *) {\n                exit(0)\n            }\n        }\n    }\n    \n    @objc func willStop(_ aNotification: Notification) {\n        DisplayDetection.sharedInstance.resetUnusedScreens()\n\n/*        if #available(macOS 14.0, *) {\n            debugLog(\"🖼️ 📢📢📢 🖼️ 📢📢📢 ☢️sonoma☢️ workaround IGNORING willStop\")\n        } else {*/\n        debugLog(\"🖼️ 📢📢📢 willStop\")\n        if !Aerial.helper.underCompanion {\n            if let player = player {\n                player.pause()\n            }\n            \n            if #available(macOS 14.0, *) {\n                debugLog(\"🖼️ ⏱️ Setting up 2-second delayed exit\")\n                DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {\n                    debugLog(\"🖼️ 🚪 Exiting application now\")\n                    exit(0)\n                }\n            }\n\n            self.stopAnimation()\n        } else {\n            if !globalPause {\n                player?.play()\n                player?.rate = globalSpeed\n            }\n        }\n        //}\n    }\n\n    // Tentative integration with companion of extra features\n    @objc func togglePause() {\n        debugLog(\"🖼️ Toggling pause\")\n        if player?.rate == 0 {\n            player?.play()\n            player?.rate = globalSpeed\n            globalPause = false\n        } else {\n            player?.pause()\n            globalPause = true\n        }\n        removePlayerFades()\n    }\n\n    @objc func nextVideo() {\n        debugLog(\"🖼️ Next video\")\n        fastFadeOut(andPlayNext: true)\n    }\n\n    @objc func skipAndHide() {\n        guard let currentVideo = currentVideo else {\n            errorLog(\"skipAndHide, no currentVideo\")\n            return\n        }\n\n        debugLog(\"🖼️ Skip video and hide\")\n        PrefsVideos.hidden.append(currentVideo.id)\n        fastFadeOut(andPlayNext: true)\n    }\n\n    @objc func getGlobalSpeed() -> Float {\n        guard let player = player else {\n            errorLog(\"getGlobalSpeed, no player\")\n            return 0\n        }\n        debugLog(\"🖼️ Current global speed : \" + String(globalSpeed))\n        return player.rate\n    }\n\n    @objc func setGlobalSpeed(_ speed : Float)  {\n        debugLog(\"🖼️ Setting speed to : \" + String(speed))\n        globalSpeed = speed\n\n        // Apply now if playing\n        if let player = player {\n            if (player.rate != 0) {\n                player.rate = globalSpeed\n            }\n        }\n    }\n\n    \n    \n    // MARK: - playNextVideo()\n    // swiftlint:disable:next cyclomatic_complexity\n    func playNextVideo() {\n        debugLog(\"🖼️ \\(self) pnv\")\n\n        clearAllLayerAnimations()\n\n        clearNotifications()\n\n        // play another video\n        let player = AVPlayer()\n        let oldPlayer = self.player\n        self.player = player\n        player.isMuted = PrefsAdvanced.muteSound\n\n        self.playerLayer.player = self.player\n        self.playerLayer.opacity = AerialView.shouldFade ? 0 : 1.0\n        if self.isPreview {\n            AerialView.previewPlayer = player\n        }\n\n        debugLog(\"🖼️ \\(self.description) Setting player for all player layers in \\(AerialView.sharedViews)\")\n        for view in AerialView.sharedViews {\n            view.playerLayer.player = player\n        }\n\n        if oldPlayer == AerialView.previewPlayer {\n            AerialView.previewView?.playerLayer.player = self.player\n        }\n\n        playerLayer.drawsAsynchronously = true\n\n        // get a list of current videos that should be excluded from the candidate selection\n        // for the next video. This prevents the same video from being shown twice in a row\n        // as well as the same video being shown on two different monitors even when sharingPlayers\n        // is false\n        let currentVideos: [AerialVideo] = AerialView.players.compactMap { (player) -> AerialVideo? in\n            (player.currentItem as? AerialPlayerItem)?.video\n        }\n\n        let (randomVideo, pshouldLoop) = VideoList.instance.randomVideo(excluding: currentVideos, isVertical: isScreenVertical())\n\n        // If we only have one video in the playlist, we can rewind it for seamless transitions\n        self.shouldLoop = pshouldLoop\n\n        guard let video = randomVideo else {\n            errorLog(\"\\(self.description) Error grabbing random video!\")\n            return\n        }\n        self.currentVideo = video\n\n        // Workaround to avoid local playback making network calls\n        let item = AerialPlayerItem(video: video)\n        if !video.isAvailableOffline {\n            if let value = PrefsVideos.vibrance[video.id], !video.isHDR() {\n                item.setVibrance(value)\n            }\n            if PrefsAdvanced.invertColors {\n                item.setColorInvert()\n            }\n\n            player.replaceCurrentItem(with: item)\n            debugLog(\"🖼️ \\(self.description) streaming video (not fully available offline) : \\(video.url)\")\n\n            guard let currentItem = player.currentItem else {\n                errorLog(\"\\(self.description) No current item!\")\n                return\n            }\n\n            debugLog(\"🖼️ \\(self.description) observing current item \\(currentItem)\")\n\n            // Descriptions and fades are set when we begin playback\n            if !self.observerWasSet {\n                observerWasSet = true\n                playerLayer.addObserver(self, forKeyPath: \"readyForDisplay\", options: .initial, context: nil)\n            }\n            \n            sendNotification(video: video)\n            setNotifications(currentItem)\n\n            player.actionAtItemEnd = AVPlayer.ActionAtItemEnd.none\n\n            // Let's never download stuff in preview...\n            if !isPreview {\n                Cache.fillOrRollCache()\n            }\n        } else {\n            // The new localpath getter\n            let localPath = VideoList.instance.localPathFor(video: video)\n\n            // let localurl = URL(fileURLWithPath: VideoCache.cachePath(forVideo: video)!)\n            let localurl = URL(fileURLWithPath: localPath)\n            let localitem = AVPlayerItem(url: localurl)\n            if !video.isHDR() {\n                let value = PrefsVideos.vibrance[video.id] ?? 0\n                localitem.setVibrance(value)\n            }\n            if PrefsAdvanced.invertColors {\n                localitem.setColorInvert()\n            }\n            \n            DispatchQueue.global(qos: .default).async { [self] in\n                player.replaceCurrentItem(with: localitem)\n                debugLog(\"🖼️ \\(self.description) playing video (OFFLINE MODE) : \\(localurl)\")\n                guard let currentItem = player.currentItem else {\n                    errorLog(\"\\(self.description) No current item!\")\n                    return\n                }\n\n                debugLog(\"🖼️ \\(self.description) observing current item \\(currentItem)\")\n\n                // Descriptions and fades are set when we begin playback\n                if !self.observerWasSet {\n                    observerWasSet = true\n                    playerLayer.addObserver(self, forKeyPath: \"readyForDisplay\", options: .initial, context: nil)\n                }\n\n                sendNotification(video: video)\n                setNotifications(currentItem)\n\n                player.actionAtItemEnd = AVPlayer.ActionAtItemEnd.none\n\n                // Let's never download stuff in preview...\n                if !isPreview {\n                    Cache.fillOrRollCache()\n                }\n            }\n        }\n    }\n\n    // Is the current screen vertical?\n    func isScreenVertical() -> Bool {\n        return self.frame.size.width < self.frame.size.height\n    }\n\n    override func keyDown(with event: NSEvent) {\n        debugLog(\"🖼️ keyDown\")\n\n        if PrefsVideos.allowSkips {\n            if event.keyCode == 124 {\n                if !isQuickFading {\n                    // If we share, just call this on our main view\n                    if AerialView.sharingPlayers {\n                        // The first view with the player gets the fade and the play next instruction,\n                        // it controls the others\n                        for view in AerialView.sharedViews where AerialView.sharedViews.first != view {\n                            view.fastFadeOut(andPlayNext: false)\n                        }\n                        AerialView.sharedViews.first!.fastFadeOut(andPlayNext: true)\n\n                    } else {\n                        // If we do independant playback we have to skip all views\n                        for view in AerialView.instanciatedViews {\n                            view.fastFadeOut(andPlayNext: true)\n                        }\n                    }\n                } else {\n                    debugLog(\"🖼️⚠️ Right arrow key currently locked\")\n                }\n            } else if event.keyCode == 125 {\n                stopAnimation()\n            } else {\n                self.nextResponder!.keyDown(with: event)\n                // super.keyDown(with: event)\n            }\n        } else {\n            self.nextResponder?.keyDown(with: event)\n            // super.keyDown(with: event)\n        }\n    }\n\n    override var acceptsFirstResponder: Bool {\n        // swiftlint:disable:next implicit_getter\n        get {\n            return true\n        }\n    }\n\n    // MARK: - Extra Animations\n    private func fastFadeOut(andPlayNext: Bool) {\n        // We need to clear the current animations running on playerLayer\n        isQuickFading = true    // Lock the use of keydown\n        playerLayer.removeAllAnimations()\n        let fadeOutAnimation = CAKeyframeAnimation(keyPath: \"opacity\")\n        fadeOutAnimation.values = [1, 0] as [Int]\n        fadeOutAnimation.keyTimes = [0, AerialView.fadeDuration] as [NSNumber]\n        if !Aerial.helper.underCompanion {\n            fadeOutAnimation.duration = AerialView.fadeDuration\n        } else {\n            fadeOutAnimation.values = [1, 1] as [Int]\n            fadeOutAnimation.duration = 0.1\n        }\n        fadeOutAnimation.delegate = self\n        fadeOutAnimation.isRemovedOnCompletion = false\n        fadeOutAnimation.calculationMode = CAAnimationCalculationMode.cubic\n        if andPlayNext {\n            playerLayer.add(fadeOutAnimation, forKey: \"quickfadeandnext\")\n        } else {\n            playerLayer.add(fadeOutAnimation, forKey: \"quickfade\")\n        }\n    }\n\n    // Stop callback for fastFadeOut\n    func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {\n        isQuickFading = false   // Release our ugly lock\n        playerLayer.opacity = 0\n        if anim == playerLayer.animation(forKey: \"quickfadeandnext\") {\n            debugLog(\"🖼️ stop and next\")\n            playerLayer.removeAllAnimations()   // Make sure we get rid of our anim\n            playNextVideo()\n        } else {\n            debugLog(\"🖼️ stop\")\n            playerLayer.removeAllAnimations()   // Make sure we get rid of our anim\n        }\n    }\n\n    // Create a move animation\n    func createMoveAnimation(layer: CALayer, to: CGPoint, duration: Double) -> CABasicAnimation {\n        let moveAnimation = CABasicAnimation(keyPath: \"position\")\n        moveAnimation.fromValue = layer.position\n        moveAnimation.toValue = to\n        moveAnimation.duration = duration\n        layer.position = to\n        return moveAnimation\n    }\n\n    // MARK: - Preferences\n\n    override var hasConfigureSheet: Bool {\n        return true\n    }\n\n    override var configureSheet: NSWindow? {\n        if let controller = preferencesController {\n            return controller.window\n        }\n\n        let controller = PanelWindowController()\n        preferencesController = controller\n        return controller.window\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Views/Layers/AnimatableLayer.swift",
    "content": "//\n//  AnimatableLayer.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 17/04/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Foundation\nimport AVKit\n\nprotocol AnimatableLayer: CALayer {\n    var layerManager: LayerManager { get set }\n\n    var lastCorner: Int { get set }\n    var isPreview: Bool { get set }\n    var baseLayer: CALayer { get set }\n    var offsets: LayerOffsets { get set }\n    var corner: InfoCorner { get set }\n\n    var currentCorner: InfoCorner? { get set }\n    var currentHeight: CGFloat? { get set }\n    var currentPosition: CGPoint? { get set }\n\n    // Lifecycle, can be overriden so this does NOT go into the extension\n    func clear(player: AVPlayer)\n    func setupForVideo(video: AerialVideo, player: AVPlayer)\n    func setContentScale(scale: CGFloat)\n\n    // Used by TextLayers only\n    func setAlignment(mode: CATextLayerAlignmentMode)\n\n    // Corner movement stuff\n    func move(toCorner: InfoCorner, fullRedraw: Bool)\n    func moveTo(point: CGPoint)\n\n    // Margins\n    func getHorizontalMargin() -> CGFloat\n    func getVerticalMargin(forCorner: InfoCorner) -> CGFloat\n}\n\nextension AnimatableLayer {\n\n    // MARK: Move layers\n    // swiftlint:disable:next cyclomatic_complexity\n    func move(toCorner: InfoCorner, fullRedraw: Bool) {\n        if let currCorner = currentCorner, !fullRedraw {\n            // Are we on the same corner ?\n            if currCorner == toCorner {\n                // And same height ?\n                if currentHeight! == frame.height {\n                    // position is reset, so we need to set it again\n                    position = currentPosition!\n                    return\n                } else {\n                    // It's a whole corner redraw, then\n                    layerManager.redrawCorner(corner: toCorner)\n                    return\n                }\n            } else {\n                // So we changed corner... we redraw our previous corner\n                // and redraw the new one too !\n                let prevCorner = currCorner\n                currentCorner = toCorner\n                layerManager.redrawCorner(corner: prevCorner)\n                layerManager.redrawCorner(corner: toCorner)\n                return\n            }\n        }\n\n        let mx = getHorizontalMargin()\n        let my = getVerticalMargin(forCorner: toCorner)\n\n        var newPos: CGPoint\n\n        switch toCorner {\n        case .topLeft:\n            anchorPoint = CGPoint(x: 0, y: 1)\n            newPos = CGPoint(x: mx, y: baseLayer.bounds.height - my)\n            setAlignment(mode: .left)\n        case .topCenter:\n            anchorPoint = CGPoint(x: 0.5, y: 1)\n            newPos = CGPoint(x: baseLayer.bounds.width/2,\n                             y: baseLayer.bounds.height-my)\n            setAlignment(mode: .center)\n        case .topRight:\n            anchorPoint = CGPoint(x: 1, y: 1)\n            newPos = CGPoint(x: baseLayer.bounds.width-mx,\n                             y: baseLayer.bounds.height-my)\n            setAlignment(mode: .right)\n        case .screenCenter:\n            anchorPoint = CGPoint(x: 0.5, y: 0)\n            newPos = CGPoint(x: baseLayer.bounds.width/2,\n                             y: baseLayer.bounds.height/2 - my + 20)\n            setAlignment(mode: .center)\n        case .bottomLeft:\n            anchorPoint = CGPoint(x: 0, y: 0)\n            newPos = CGPoint(x: mx, y: my)\n            setAlignment(mode: .left)\n        case .bottomCenter:\n            anchorPoint = CGPoint(x: 0.5, y: 0)\n            newPos = CGPoint(x: baseLayer.bounds.width/2, y: my)\n            setAlignment(mode: .center)\n        case .absTopRight:\n            anchorPoint = CGPoint(x: 1, y: 1)\n            newPos = CGPoint(x: baseLayer.bounds.width-mx,\n                             y: baseLayer.bounds.height-10)\n            setAlignment(mode: .right)\n        default:    // bottomRight\n            anchorPoint = CGPoint(x: 1, y: 0)\n            newPos = CGPoint(x: baseLayer.bounds.width-mx, y: my)\n            setAlignment(mode: .right)\n        }\n\n        moveTo(point: newPos)\n\n        let offset = offsets.corner[toCorner] == 0\n            ? my + frame.height\n            : frame.height\n\n        // Make sure we update our offsets for the next layer\n        offsets.corner[toCorner]! += offset\n\n        // We need to save for next time !\n        currentCorner = toCorner\n        currentHeight = frame.height\n        currentPosition = newPos\n    }\n\n    // Move in 1 second to a position\n    // Those are masked by the transition between fades\n    func moveTo(point: CGPoint) {\n        CATransaction.begin()\n        CATransaction.setValue(1, forKey: kCATransactionAnimationDuration)\n        self.position = point\n        CATransaction.commit()\n    }\n\n    // MARK: Corners\n    // Handle the random corner\n    func getCorner() -> InfoCorner {\n        if corner != .random {\n            return corner\n        }\n\n        // Find a new corner, different from the previous one\n        var newCorner = getRandomCorner()\n\n        while newCorner == lastCorner {\n            newCorner = getRandomCorner()\n        }\n\n        return InfoCorner(rawValue: newCorner)!\n    }\n\n    // Return a strict corner, not a center pos\n    func getRandomCorner() -> Int {\n        let rnd = Int.random(in: 0...3)\n        if rnd == 0 {\n            return 0\n        } else if rnd == 1 {\n            return 2\n        } else if rnd == 2 {\n            return 3\n        } else {\n            return 5\n        }\n    }\n\n    // MARK: - Margins\n\n    // Get the horizontal margin to the border of the screen\n    func getHorizontalMargin() -> CGFloat {\n        // We override for previews\n        if isPreview {\n            return 10\n        }\n\n        var mx: CGFloat = 50\n\n        // We may override margins\n        if PrefsInfo.overrideMargins {\n            mx = CGFloat(PrefsInfo.marginX)\n        }\n\n        return mx\n    }\n\n    // Get the horizontal margin to the border of the screen\n    func getVerticalMargin(forCorner: InfoCorner) -> CGFloat {\n        // If we already have an offset, use that !\n        if offsets.corner[forCorner] != 0 {\n            return offsets.corner[forCorner]!\n        }\n\n        // We override for previews\n        if isPreview {\n            offsets.corner[forCorner] = 10\n            return offsets.corner[forCorner]!\n        }\n\n        var my: CGFloat = 50\n\n        // We may override margins\n        if PrefsInfo.overrideMargins {\n            my = CGFloat(PrefsInfo.marginY)\n        }\n\n        offsets.corner[forCorner] = my\n        return my\n    }\n\n    // MARK: Animations\n\n    // Create a Fade In/Out animation\n    func createFadeInOutAnimation(duration: Double) -> CAKeyframeAnimation {\n        let fadeAnimation = CAKeyframeAnimation(keyPath: \"opacity\")\n        fadeAnimation.values = [0, 0, 1, 1, 0] as [NSNumber]\n        fadeAnimation.keyTimes = [\n            0,\n            Double(1 / duration ),\n            Double((1 + AerialView.textFadeDuration) / duration),\n            Double(1 - AerialView.textFadeDuration / duration),\n            1\n            ] as [NSNumber]\n        fadeAnimation.duration = duration\n        return fadeAnimation\n    }\n\n    // Create a Fade In (only) animation, used for things that\n    // should always be on screen (clock, etc)\n    func createFadeInAnimation() -> CAKeyframeAnimation {\n        let fadeAnimation = CAKeyframeAnimation(keyPath: \"opacity\")\n        fadeAnimation.values = [0, 0, 1] as [NSNumber]\n        fadeAnimation.keyTimes = [\n            0,\n            Double(1 / (1 + AerialView.textFadeDuration)),\n            Double(1)\n            ] as [NSNumber]\n        fadeAnimation.duration = 1 + AerialView.textFadeDuration\n        return fadeAnimation\n    }\n}\n\n// MARK: Extra helpers for text layers\n\nextension CATextLayer {\n    // Calculate the screen rect that will be used by our string\n    func calculateRect(string: String, font: NSFont) -> CGRect {\n        let boundingRect = self.frame.size\n\n        // We need an attributed string to take the font into account\n        let attributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.font: font as Any]\n        let str = NSAttributedString(string: string, attributes: attributes)\n\n        // Calculate bounding box\n        let rect = str.boundingRect(with: boundingRect, options: [.truncatesLastVisibleLine, .usesLineFragmentOrigin])\n\n        return CGRect(x: rect.origin.x, y: rect.origin.y, width: rect.width+10, height: rect.height + 10)\n    }\n\n    func calculateRect(string: String, font: NSFont, maxWidth: Double) -> CGRect {\n        let boundingRect = CGSize(width: maxWidth, height: Double(self.frame.size.height))\n\n        // We need an attributed string to take the font into account\n        let attributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.font: font as Any]\n        let str = NSAttributedString(string: string, attributes: attributes)\n\n        // Calculate bounding box\n        let rect = str.boundingRect(with: boundingRect, options: [.truncatesLastVisibleLine, .usesLineFragmentOrigin])\n\n        return CGRect(x: rect.origin.x, y: rect.origin.y, width: rect.width+10, height: rect.height + 10)\n    }\n\n    // Get the font and font size\n    func makeFont(name: String, size: Double) -> (NSFont, CGFloat) {\n        let fontSize = CGFloat(size)    // Mayyybe some isPreview global somewhere\n\n        // Get font with a fallback in case\n        var font = NSFont(name: \"Helvetica Neue Medium\", size: 28)\n        if let tryFont = NSFont(name: name, size: fontSize) {\n            font = tryFont\n        }\n\n        return (font!, fontSize)\n    }\n\n    // Set font & size from some Aerial Preferences\n    func setFont(name: String, size: Double) {\n        (self.font, self.fontSize) = self.makeFont(name: name, size: size)\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Views/Layers/AnimationLayer.swift",
    "content": "//\n//  AnimationLayer.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 17/04/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Foundation\nimport AVKit\n\nclass AnimationLayer: CALayer, AnimatableLayer {\n    var layerManager: LayerManager\n    var lastCorner = -1\n    var isPreview: Bool\n    var baseLayer: CALayer\n    var offsets: LayerOffsets\n    var corner: InfoCorner = .bottomLeft\n\n    var currentCorner: InfoCorner?\n    var currentHeight: CGFloat?\n    var currentPosition: CGPoint?\n\n    func clear(player: AVPlayer) {} // Optional\n    func setupForVideo(video: AerialVideo, player: AVPlayer) {} // Pretty much required\n    func setContentScale(scale: CGFloat) {}\n\n    // Called by the extension to set the text alignment\n    func setAlignment(mode: CATextLayerAlignmentMode) {\n        // alignmentMode = mode\n    }\n\n    // Super init, used by CATextLayer's setFont, etc\n    override init(layer: Any) {\n        layerManager = (layer as! AnimationLayer).layerManager\n        isPreview = (layer as! AnimationLayer).isPreview\n        baseLayer = (layer as! AnimationLayer).baseLayer\n        offsets = (layer as! AnimationLayer).offsets\n        corner = (layer as! AnimationLayer).corner\n        super.init(layer: layer)\n    }\n\n    required init?(coder: NSCoder) {\n        fatalError(\"init(coder:) has not been implemented\")\n    }\n\n    // Our init\n    init(withLayer: CALayer, isPreview: Bool, offsets: LayerOffsets, manager: LayerManager) {\n        self.layerManager = manager\n        self.isPreview = isPreview\n        self.baseLayer = withLayer\n        self.offsets = offsets\n        super.init()\n\n        // Same size as the screen\n        self.frame = withLayer.bounds\n        // Starts hidden, with a bit of shadow for text separation\n        self.opacity = 0\n        self.shadowRadius = CGFloat(PrefsInfo.shadowRadius)\n        self.shadowOpacity = PrefsInfo.shadowOpacity\n        self.shadowOffset = CGSize(width: PrefsInfo.shadowOffsetX,\n                                   height: PrefsInfo.shadowOffsetY)\n\n        self.shadowColor = CGColor.black\n    }\n\n    // Update and move to a corner\n    func update(redraw: Bool = false) {\n        // This is the rect resized to our string\n        let newCorner = getCorner()\n\n        // For non text layer, we need to do this here, this is done in calculateRect for text layers...\n        if frame.size.width+10 > offsets.maxWidth[corner]! {\n            offsets.maxWidth[corner] = frame.size.width+10\n        }\n        move(toCorner: newCorner, fullRedraw: false)\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Views/Layers/AnimationTextLayer.swift",
    "content": "//\n//  AnimationLayer.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 11/12/2019.\n//  Copyright © 2019 Guillaume Louel. All rights reserved.\n//\n\nimport Foundation\nimport AVKit\n\n// s*wiftlint:disable:next type_body_length\nclass AnimationTextLayer: CATextLayer, AnimatableLayer {\n    var layerManager: LayerManager\n    var lastCorner = -1\n    var isPreview: Bool\n    var baseLayer: CALayer\n    var offsets: LayerOffsets\n    var corner: InfoCorner = .bottomLeft\n\n    var currentCorner: InfoCorner?\n    var currentHeight: CGFloat?\n    var currentPosition: CGPoint?\n\n    // Super init, used by CATextLayer's setFont, etc\n    override init(layer: Any) {\n        layerManager = (layer as! AnimationTextLayer).layerManager\n        isPreview = (layer as! AnimationTextLayer).isPreview\n        baseLayer = (layer as! AnimationTextLayer).baseLayer\n        offsets = (layer as! AnimationTextLayer).offsets\n        corner = (layer as! AnimationTextLayer).corner\n        super.init(layer: layer)\n    }\n\n    required init?(coder: NSCoder) {\n        fatalError(\"init(coder:) has not been implemented\")\n    }\n\n    // Our init\n    init(withLayer: CALayer, isPreview: Bool, offsets: LayerOffsets, manager: LayerManager) {\n        self.layerManager = manager\n        self.isPreview = isPreview\n        self.baseLayer = withLayer\n        self.offsets = offsets\n        super.init()\n\n        // Same size as the screen\n        self.frame = withLayer.bounds\n        // Starts hidden, with a bit of shadow for text separation\n        self.opacity = 0\n        self.shadowRadius = CGFloat(PrefsInfo.shadowRadius)\n        self.shadowOpacity = PrefsInfo.shadowOpacity\n        self.shadowOffset = CGSize(width: PrefsInfo.shadowOffsetX,\n                                   height: PrefsInfo.shadowOffsetY)\n\n        self.shadowColor = CGColor.black\n    }\n\n    // To be overriden if needed\n    func clear(player: AVPlayer) {} // Optional\n    func setupForVideo(video: AerialVideo, player: AVPlayer) {} // Pretty much required\n    func setContentScale(scale: CGFloat) {}\n\n    // Called by the extension to set the text alignment\n    func setAlignment(mode: CATextLayerAlignmentMode) {\n        alignmentMode = mode\n    }\n\n    // Update the string and move to a corner\n    func update(string: String) {\n        // Setup string\n        self.string = string\n        self.isWrapped = true\n\n        // This is the rect resized to our string\n        let newCorner = getCorner()\n        frame = calculateRect(string: string, font: font as! NSFont, newCorner: newCorner)\n        //debugLog(frame.debugDescription)\n        move(toCorner: newCorner, fullRedraw: false)\n    }\n\n    // MARK: Text/Font stuff\n    // Calculate the screen rect that will be used by our string\n    func calculateRect(string: String, font: NSFont, newCorner: InfoCorner) -> CGRect {\n        let mx = getHorizontalMargin()\n\n        var oppoMargin: CGFloat\n\n        if self is LocationLayer {\n            oppoMargin = getOppoMargin(corner: newCorner)\n        } else {\n            oppoMargin = 0\n        }\n\n        let boundingRect = CGSize(width: baseLayer.visibleRect.size.width-2*mx-oppoMargin,\n                                  height: baseLayer.visibleRect.size.height)\n\n        // We need an attributed string to take the font into account\n        let attributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.font: font as Any]\n        let str = NSAttributedString(string: string, attributes: attributes)\n\n        // Calculate bounding box\n        let rect = str.boundingRect(with: boundingRect, options: [.truncatesLastVisibleLine, .usesLineFragmentOrigin])\n\n        if !(self is LocationLayer) {\n            if rect.width+10 > offsets.maxWidth[corner]! {\n                offsets.maxWidth[corner] = rect.width+10\n            }\n        }\n\n        // Last line won't appear if we don't adjust a bit (why!?)\n        return CGRect(x: rect.origin.x, y: rect.origin.y, width: rect.width+10, height: rect.height + 10)\n    }\n\n    func getOppoMargin(corner: InfoCorner) -> CGFloat {\n        // Handle the special cases of having something in the center\n        if offsets.maxWidth[.topCenter]! > 0 && (corner == .topLeft || corner == .topRight) {\n            return (baseLayer.visibleRect.size.width + offsets.maxWidth[.topCenter]!) / 2\n        }\n        if offsets.maxWidth[.bottomCenter]! > 0 && (corner == .bottomLeft || corner == .bottomRight) {\n            return (baseLayer.visibleRect.size.width + offsets.maxWidth[.bottomCenter]!) / 2\n        }\n\n        // Then the regular cases\n        switch corner {\n        case .topLeft:\n            return offsets.maxWidth[.topRight]!\n        case .topRight:\n            return offsets.maxWidth[.topLeft]!\n        case .bottomLeft:\n            return offsets.maxWidth[.bottomRight]!\n        default: // .bottomRight, we only allow the 4 corners for random\n            return offsets.maxWidth[.bottomLeft]!\n        }\n    }\n\n    // Get the font and font size\n    func getFont(name: String, size: Double) -> (NSFont, CGFloat) {\n        let fontSize = isPreview ? 12 : CGFloat(size)\n\n        // Get font with a fallback in case\n        var font = NSFont(name: \"Helvetica Neue Medium\", size: 28)\n        if let tryFont = NSFont(name: name, size: fontSize) {\n            font = tryFont\n        }\n\n        return (font!, fontSize)\n    }\n\n    // Transform a date by setting it to today (or tommorrow)\n    func todayizeDate(_ target: Date, strict: Bool) -> Date {\n        let now = Date()\n\n        let calendar = Calendar.current\n        var targetComponent = calendar.dateComponents([.year, .month, .day, .hour, .minute, .second], from: target)\n        let nowComponent = calendar.dateComponents([.year, .month, .day, .hour, .minute, .second], from: now)\n\n        targetComponent.year = nowComponent.year\n        targetComponent.month = nowComponent.month\n        targetComponent.day = nowComponent.day\n\n        let candidate = Calendar.current.date(from: targetComponent) ?? target\n\n        if strict {\n            return candidate\n        } else {\n            // In non strict mode, if the hour is passed already\n            // we return tomorrow\n            if candidate > now {\n                return candidate\n            } else {\n                return candidate.tomorrow ?? candidate\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Views/Layers/BatteryIconLayer.swift",
    "content": "//\n//  BatteryIconLayer.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 01/05/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Foundation\nimport AVKit\n\nclass BatteryIconLayer: AnimationLayer {\n    var config: PrefsInfo.Battery?\n    var wasSetup = false\n    var batteryTimer: Timer?\n\n    var iconLayer: CALayer?\n    var textLayer: CATextLayer?\n    var charging: CALayer?\n\n    var backupHeight: CGFloat?\n\n    override init(layer: Any) {\n        super.init(layer: layer)\n    }\n\n    required init?(coder: NSCoder) {\n        fatalError(\"init(coder:) has not been implemented\")\n    }\n\n    // Our inits\n    override init(withLayer: CALayer, isPreview: Bool, offsets: LayerOffsets, manager: LayerManager) {\n        super.init(withLayer: withLayer, isPreview: isPreview, offsets: offsets, manager: manager)\n\n        // Always on layers should start with full opacity\n        self.opacity = 1\n    }\n\n    convenience init(withLayer: CALayer, isPreview: Bool, offsets: LayerOffsets, manager: LayerManager, config: PrefsInfo.Battery) {\n        self.init(withLayer: withLayer, isPreview: isPreview, offsets: offsets, manager: manager)\n        self.config = config\n\n/*        // Set our layer's font & corner now\n        (self.font, self.fontSize) = getFont(name: config.fontName,\n                                             size: config.fontSize)*/\n        self.corner = config.corner\n        iconLayer = CALayer()\n        charging = CALayer()\n        textLayer = CATextLayer()\n    }\n\n    func setup() {\n        let imagePath = Bundle(for: PanelWindowController.self).path(\n            forResource: \"battery.0\",\n            ofType: \"pdf\")\n\n        guard let img = NSImage(contentsOfFile: imagePath!) else {\n            errorLog(\"BatteryIconLayer couldn't load the icon files\")\n            return\n        }\n\n        iconLayer!.frame.size.height = img.size.height / 3\n        iconLayer!.frame.size.width = img.size.width / 3\n        iconLayer!.anchorPoint = CGPoint(x: 1, y: 1)\n        iconLayer!.contents = img\n\n        frame.size.height = iconLayer!.frame.size.height + 10\n        frame.size.width = iconLayer!.frame.size.width + 20\n\n        // We need that for later\n        backupHeight = frame.size.height\n\n        iconLayer!.position.x = frame.size.width\n        iconLayer!.position.y = frame.size.height\n\n        textLayer!.frame = CGRect(x: 20, y: 0,\n                                  width: iconLayer!.frame.size.width-5,\n                                  height: iconLayer!.frame.size.height)\n        textLayer!.fontSize = 15\n        textLayer!.alignmentMode = .center\n        textLayer!.string = \"100%\"\n        textLayer!.foregroundColor = .white\n        textLayer!.position.y = 19.5\n\n        self.addSublayer(iconLayer!)\n        self.addSublayer(textLayer!)\n\n        let chargingPath = Bundle(for: PanelWindowController.self).path(\n            forResource: \"bolt.fill\",\n            ofType: \"pdf\")\n\n        if chargingPath != nil {\n            let cimg = NSImage(contentsOfFile: chargingPath!)\n            charging!.contents = cimg\n            charging!.frame.size.height = cimg!.size.height / 6\n            charging!.frame.size.width = cimg!.size.width / 6\n            charging!.anchorPoint = CGPoint(x: 0, y: 0.5)\n            charging!.position.y = frame.size.height/2+5\n            charging!.position.x = 2\n            self.addSublayer(charging!)\n        }\n\n    }\n\n    override func setContentScale(scale: CGFloat) {\n        self.contentsScale = scale\n        iconLayer!.contentsScale = scale\n        textLayer!.contentsScale = scale\n        charging!.contentsScale = scale\n    }\n\n    override func setupForVideo(video: AerialVideo, player: AVPlayer) {\n        // Only run this once\n        if !wasSetup {\n            wasSetup = true\n\n            setup()\n\n            // Update also moves and align everything... So we call it here\n            self.updateStatus()\n            self.update()\n\n            if #available(OSX 10.12, *) {\n                batteryTimer = Timer.scheduledTimer(withTimeInterval: 10.0, repeats: true, block: { (_) in\n                        self.updateStatus()\n                        self.update()\n                    })\n            }\n\n            let fadeAnimation = self.createFadeInAnimation()\n            add(fadeAnimation, forKey: \"textfade\")\n        }\n    }\n\n    func updateStatus() {\n        let percent = Battery.getRemainingPercent()\n\n        if PrefsInfo.battery.disableWhenFull {\n            if percent == 100 {\n                opacity = 0\n                frame.size.height = 1\n            } else {\n                opacity = 1\n                frame.size.height = backupHeight!\n            }\n        }\n\n        // Should we put the bolt or not\n        if !Battery.isUnplugged() {\n            charging!.opacity = 1\n        } else {\n            charging!.opacity = 0\n        }\n\n        // Update the string\n        textLayer!.string = \"\\(percent) %\"\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Views/Layers/ClockLayer.swift",
    "content": "//\n//  ClockLayer.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 12/12/2019.\n//  Copyright © 2019 Guillaume Louel. All rights reserved.\n//\n\nimport Foundation\nimport AVKit\n\nclass ClockLayer: AnimationTextLayer {\n    var config: PrefsInfo.Clock?\n    var wasSetup = false\n    var clockTimer: Timer?\n\n    override init(layer: Any) {\n        super.init(layer: layer)\n    }\n\n    required init?(coder: NSCoder) {\n        fatalError(\"init(coder:) has not been implemented\")\n    }\n\n    // Our inits\n    override init(withLayer: CALayer, isPreview: Bool, offsets: LayerOffsets, manager: LayerManager) {\n        super.init(withLayer: withLayer, isPreview: isPreview, offsets: offsets, manager: manager)\n\n        // Always on layers should start with full opacity\n        self.opacity = 1\n    }\n\n    convenience init(withLayer: CALayer, isPreview: Bool, offsets: LayerOffsets, manager: LayerManager, config: PrefsInfo.Clock) {\n        self.init(withLayer: withLayer, isPreview: isPreview, offsets: offsets, manager: manager)\n        self.config = config\n\n        // Set our layer's font & corner now\n        (self.font, self.fontSize) = getFont(name: config.fontName,\n                                             size: config.fontSize)\n        self.corner = config.corner\n    }\n\n    // Called at each new video, we only setup once though !\n    override func setupForVideo(video: AerialVideo, player: AVPlayer) {\n        // Only run this once\n        if !wasSetup {\n            wasSetup = true\n\n            if #available(OSX 10.12, *) {\n                clockTimer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true, block: { (_) in\n                    self.update(string: self.getTimeString())\n                })\n            }\n\n            update(string: getTimeString())\n            let fadeAnimation = self.createFadeInAnimation()\n            add(fadeAnimation, forKey: \"textfade\")\n        }\n    }\n\n    func getTimeString() -> String {\n        var locale = Locale.current\n        if PrefsAdvanced.ciOverrideLanguage != \"\" {\n            locale = Locale(identifier: PrefsAdvanced.ciOverrideLanguage)\n        }\n\n        // Handle the manual override\n        if PrefsInfo.clock.clockFormat == .t12hours {\n            locale = Locale(identifier: \"en_US\")\n        } else if PrefsInfo.clock.clockFormat != .custom {\n            locale = Locale(identifier: \"fr_FR\")\n        }\n\n        let dateFormatter = DateFormatter()\n        if config!.clockFormat == .custom {\n            dateFormatter.dateFormat = DateFormatter.dateFormat(fromTemplate: PrefsInfo.customTimeFormat, options: 0, locale: locale)\n        } else {\n            dateFormatter.dateFormat = DateFormatter.dateFormat(fromTemplate: config!.showSeconds\n                ? \"j:mm:ss\"\n                : \"j:mm\", options: 0, locale: locale)\n        }\n\n        if config!.hideAmPm {\n            dateFormatter.amSymbol = \"\"\n            dateFormatter.pmSymbol = \"\"\n        }\n\n        return dateFormatter.string(from: Date())\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Views/Layers/CountdownLayer.swift",
    "content": "//\n//  CountdownLayer.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 13/02/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Foundation\nimport AVKit\n\nclass CountdownLayer: AnimationTextLayer {\n    var config: PrefsInfo.Countdown?\n    var wasSetup = false\n    var countdownTimer: Timer?\n\n    override init(layer: Any) {\n        super.init(layer: layer)\n    }\n\n    required init?(coder: NSCoder) {\n        fatalError(\"init(coder:) has not been implemented\")\n    }\n\n    // Our inits\n    override init(withLayer: CALayer, isPreview: Bool, offsets: LayerOffsets, manager: LayerManager) {\n        super.init(withLayer: withLayer, isPreview: isPreview, offsets: offsets, manager: manager)\n\n        // Always on layers should start with full opacity\n        self.opacity = 1\n    }\n\n    convenience init(withLayer: CALayer, isPreview: Bool, offsets: LayerOffsets, manager: LayerManager, config: PrefsInfo.Countdown) {\n        self.init(withLayer: withLayer, isPreview: isPreview, offsets: offsets, manager: manager)\n        self.config = config\n\n        // Set our layer's font & corner now\n        (self.font, self.fontSize) = getFont(name: config.fontName,\n                                             size: config.fontSize)\n        self.corner = config.corner\n    }\n\n    // Called at each new video, we only setup once though !\n    override func setupForVideo(video: AerialVideo, player: AVPlayer) {\n        // Only run this once\n        if !wasSetup {\n            wasSetup = true\n\n            if shouldCountdown() {\n                if #available(OSX 10.12, *) {\n                    countdownTimer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true, block: { (_) in\n                        self.update(string: self.getTimeString())\n                    })\n                }\n\n                update(string: getTimeString())\n                let fadeAnimation = self.createFadeInAnimation()\n                add(fadeAnimation, forKey: \"textfade\")\n            }\n        }\n    }\n\n    func shouldCountdown() -> Bool {\n        let now = Date()\n        var target = PrefsInfo.countdown.targetDate\n        var trigger = PrefsInfo.countdown.triggerDate\n\n        // We ignore the day, in timeOfDay mode by normalizing it to today\n        if config!.mode == .timeOfDay {\n            target = todayizeDate(target, strict: false)\n            trigger = todayizeDate(trigger, strict: true)\n        }\n\n        // We only start the countdown if we're later than the trigger\n        if config!.enforceInterval {\n            if trigger > now {\n                return false\n            }\n        }\n\n        // Are we still before the countdown date or not ?\n        if now < target {\n            return true\n        }\n\n        return false\n    }\n\n    func getTimeString() -> String {\n        if #available(OSX 10.12, *) {\n            // Handle locale\n            var locale = Locale(identifier: Locale.preferredLanguages[0])\n            if PrefsAdvanced.ciOverrideLanguage != \"\" {\n                locale = Locale(identifier: PrefsAdvanced.ciOverrideLanguage)\n            }\n\n            var calendar = Calendar.current\n            calendar.locale = locale\n\n            let dateComponentsFormatter = DateComponentsFormatter()\n            dateComponentsFormatter.calendar = calendar\n\n            if config!.showSeconds {\n                dateComponentsFormatter.allowedUnits = [.day, .hour, .minute, .second]\n                dateComponentsFormatter.maximumUnitCount = 4\n            } else {\n                dateComponentsFormatter.allowedUnits = [.day, .hour, .minute]\n                dateComponentsFormatter.maximumUnitCount = 3\n            }\n            dateComponentsFormatter.unitsStyle = .full\n\n            var target = PrefsInfo.countdown.targetDate\n\n            // We ignore the day, in timeOfDay mode by normalizing it to today\n            if config!.mode == .timeOfDay {\n                target = todayizeDate(target, strict: false)\n            }\n\n            return dateComponentsFormatter.string(from: Date(), to: target) ?? \"\"\n        } else {\n            // Fallback on earlier versions\n            return \"\"\n        }\n    }\n}\n\nextension Date {\n    var tomorrow: Date? {\n        return Calendar.current.date(byAdding: .day, value: 1, to: self)\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Views/Layers/DateLayer.swift",
    "content": "//\n//  DateLayer.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 23/03/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Foundation\nimport AVKit\n\nclass DateLayer: AnimationTextLayer {\n    var config: PrefsInfo.IDate?\n    var wasSetup = false\n    var dateTimer: Timer?\n\n    override init(layer: Any) {\n        super.init(layer: layer)\n    }\n\n    required init?(coder: NSCoder) {\n        fatalError(\"init(coder:) has not been implemented\")\n    }\n\n    // Our inits\n    override init(withLayer: CALayer, isPreview: Bool, offsets: LayerOffsets, manager: LayerManager) {\n        super.init(withLayer: withLayer, isPreview: isPreview, offsets: offsets, manager: manager)\n\n        // Always on layers should start with full opacity\n        self.opacity = 1\n    }\n\n    convenience init(withLayer: CALayer, isPreview: Bool, offsets: LayerOffsets, manager: LayerManager, config: PrefsInfo.IDate) {\n        self.init(withLayer: withLayer, isPreview: isPreview, offsets: offsets, manager: manager)\n        self.config = config\n\n        // Set our layer's font & corner now\n        (self.font, self.fontSize) = getFont(name: config.fontName,\n                                             size: config.fontSize)\n        self.corner = config.corner\n    }\n\n    // Called at each new video, we only setup once though !\n    override func setupForVideo(video: AerialVideo, player: AVPlayer) {\n        // Only run this once\n        if !wasSetup {\n            wasSetup = true\n\n            if #available(OSX 10.12, *) {\n                dateTimer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true, block: { (_) in\n                    self.update(string: self.getTimeString())\n                })\n            }\n\n            update(string: getTimeString())\n            let fadeAnimation = self.createFadeInAnimation()\n            add(fadeAnimation, forKey: \"textfade\")\n        }\n    }\n\n    func getTimeString() -> String {\n        // Handle locale\n        var locale = Locale(identifier: Locale.preferredLanguages[0])\n        if PrefsAdvanced.ciOverrideLanguage != \"\" {\n            locale = Locale(identifier: PrefsAdvanced.ciOverrideLanguage)\n        }\n        var template = \"\"\n\n        let dateFormatter = DateFormatter()\n        if config!.format == .textual {\n            if config!.withYear {\n                template = \"EEEE, MMMM dd, yyyy\"\n            } else {\n                template = \"EEEE, MMMM dd\"\n            }\n\n            dateFormatter.dateFormat = DateFormatter.dateFormat(fromTemplate: template, options: 0, locale: locale)\n            dateFormatter.locale = locale\n            return dateFormatter.string(from: Date()).capitalizeFirstLetter()\n\n        } else if config!.format == .compact {\n            if config!.withYear {\n                template = \"MM/dd/yy\"\n            } else {\n                template = \"MM/dd\"\n            }\n\n            dateFormatter.dateFormat = DateFormatter.dateFormat(fromTemplate: template, options: 0, locale: locale)\n            dateFormatter.locale = locale\n            return dateFormatter.string(from: Date()).capitalizeFirstLetter()\n        } else {\n            let RFC3339DateFormatter = DateFormatter()\n            RFC3339DateFormatter.locale = Locale(identifier: \"en_US_POSIX\")\n            RFC3339DateFormatter.dateFormat = PrefsInfo.customDateFormat\n\n            return RFC3339DateFormatter.string(from: Date())\n        }\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Views/Layers/DownloadIndicatorLayer.swift",
    "content": "//\n//  UpdatesLayer.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 11/02/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Foundation\nimport AVKit\n\nclass DownloadIndicatorLayer: AnimationTextLayer {\n    var config: PrefsInfo.Updates?\n    var wasSetup = false\n    var updateTimer: Timer?\n\n    override init(layer: Any) {\n        super.init(layer: layer)\n    }\n\n    required init?(coder: NSCoder) {\n        fatalError(\"init(coder:) has not been implemented\")\n    }\n\n    // Our inits\n    override init(withLayer: CALayer, isPreview: Bool, offsets: LayerOffsets, manager: LayerManager) {\n        super.init(withLayer: withLayer, isPreview: isPreview, offsets: offsets, manager: manager)\n\n        // We start with a full opacity\n        self.opacity = 1\n    }\n\n    convenience init(withLayer: CALayer, isPreview: Bool, offsets: LayerOffsets, manager: LayerManager, config: PrefsInfo.Updates) {\n        self.init(withLayer: withLayer, isPreview: isPreview, offsets: offsets, manager: manager)\n        self.config = config\n\n        // Set our layer's font & corner now\n        (self.font, self.fontSize) = getFont(name: config.fontName,\n                                             size: config.fontSize)\n        self.corner = .absTopRight\n    }\n\n    override func setupForVideo(video: AerialVideo, player: AVPlayer) {\n        if !wasSetup && PrefsCache.showBackgroundDownloads {\n            update(string: \"\")\n            setupDownloadIndicatorLayer()\n        }\n    }\n\n    // Setup the callbacks\n    func setupDownloadIndicatorLayer() {\n        // Setup the updates for the download status\n        let videoManager = VideoManager.sharedInstance\n        videoManager.addCallback { done, total in\n            self.updateDownloads(done: done, total: total, progress: 0)\n        }\n        videoManager.addProgressCallback { done, total, progress in\n            self.updateDownloads(done: done, total: total, progress: progress)\n        }\n    }\n\n    func updateDownloads(done: Int, total: Int, progress: Double) {\n        if total == 0 {\n            update(string: \"\")\n        } else {\n            let progInt = Int(progress * 100)\n            update(string: \"Downloading: \\(progInt) %\")\n        }\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Views/Layers/LayerManager.swift",
    "content": "//\n//  LayerManager.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 12/12/2019.\n//  Copyright © 2019 Guillaume Louel. All rights reserved.\n//\n\nimport Foundation\nimport AVKit\n\nclass LayerManager {\n    var additionalLayers = [AnimatableLayer]()\n    let offsets = LayerOffsets()\n    var isPreview: Bool\n    var frame: CGRect?\n\n    init(isPreview: Bool) {\n        self.isPreview = isPreview\n    }\n\n    // Initial setup of all layers, at Aerial startup\n    func setupExtraLayers(layer: CALayer, frame: CGRect) {\n        self.frame = frame\n\n        var topRow = [InfoType]()\n        var bottomRow = [InfoType]()\n\n        // The list of known layers is in an ordered array\n        // we need to split the bottom row though, as drawing them \"in order\" would look\n        // reversed to users as we draw from the corner out\n        for layerType in PrefsInfo.layers {\n            let pos = PrefsInfo.ofType(layerType).corner\n\n            if pos == .topCenter || pos == .topLeft || pos == .topRight || pos == .screenCenter {\n                topRow.append(layerType)\n            } else {\n                bottomRow.append(layerType)\n            }\n        }\n\n        // Then add top row\n        for layerType in topRow {\n            addLayerForType(layerType, layer: layer)\n        }\n\n        // Then we may need to add our special update layer\n        // It doesn't show in the main UI, it's linked to\n        // options in the Updates tab\n\n        // And reversed bottomRow\n        for layerType in bottomRow.reversed() {\n            addLayerForType(layerType, layer: layer)\n        }\n\n    }\n\n    // swiftlint:disable:next cyclomatic_complexity\n    private func addLayerForType(_ layerType: InfoType, layer: CALayer) {\n        var newLayer: AnimatableLayer?\n\n        if PrefsInfo.ofType(layerType).isEnabled && shouldEnableOnScreen(PrefsInfo.ofType(layerType).displays) {\n            switch layerType {\n            case .location:\n                newLayer = LocationLayer(withLayer: layer, isPreview: isPreview, offsets: offsets, manager: self, config: PrefsInfo.location)\n            case .message:\n                newLayer = MessageLayer(withLayer: layer, isPreview: isPreview, offsets: offsets, manager: self, config: PrefsInfo.message)\n            case .clock:\n                newLayer = ClockLayer(withLayer: layer, isPreview: isPreview, offsets: offsets, manager: self, config: PrefsInfo.clock)\n            case .date:\n                newLayer = DateLayer(withLayer: layer, isPreview: isPreview, offsets: offsets, manager: self, config: PrefsInfo.date)\n            case .battery:\n                newLayer = BatteryIconLayer(withLayer: layer, isPreview: isPreview, offsets: offsets, manager: self, config: PrefsInfo.battery)\n            case .updates:\n                newLayer = DownloadIndicatorLayer(withLayer: layer, isPreview: isPreview, offsets: offsets, manager: self, config: PrefsInfo.updates)\n            case .weather:\n                newLayer = WeatherLayer(withLayer: layer, isPreview: isPreview, offsets: offsets, manager: self, config: PrefsInfo.weather)\n            case .countdown:\n                newLayer = CountdownLayer(withLayer: layer, isPreview: isPreview, offsets: offsets, manager: self, config: PrefsInfo.countdown)\n            case .timer:\n                newLayer = TimerLayer(withLayer: layer, isPreview: isPreview, offsets: offsets, manager: self, config: PrefsInfo.timer)\n            case .music:\n                newLayer = MusicLayer(withLayer: layer, isPreview: isPreview, offsets: offsets, manager: self, config: PrefsInfo.music)\n            }\n        }\n\n        if let nLayer = newLayer {\n            nLayer.drawsAsynchronously = true\n\n            if !PrefsInfo.highQualityTextRendering {\n                // This seems to help on some configurations\n                // It has no impact on others and wrecks retina fonts though...\n                nLayer.shouldRasterize = true\n            }\n            additionalLayers.append(nLayer)\n            layer.addSublayer(nLayer)\n        }\n\n    }\n\n    // Each layer may not be displayed on each screen\n    func shouldEnableOnScreen(_ displayMode: InfoDisplays) -> Bool {\n        let displayDetection = DisplayDetection.sharedInstance\n        let thisScreen = displayDetection.findScreenWith(frame: frame!)\n\n        if let screen = thisScreen, !isPreview {\n            switch displayMode {\n            case .allDisplays:\n                debugLog(\"allDisplays\")\n                return true\n            case .mainOnly:\n                debugLog(\"mainOnly\")\n                return screen.isMain\n            case .secondaryOnly:\n                debugLog(\"secOnly\")\n                return !screen.isMain\n            }\n        }\n\n        // If it's an unknown screen or a preview, we leave it enabled\n        return true\n    }\n\n    // Called before starting a new video\n    func clearLayerAnimations(player: AVPlayer) {\n        for layer in additionalLayers {\n            print(layer)\n            layer.clear(player: player)\n            layer.removeAllAnimations()\n        }\n    }\n    \n    func removeAllLayers() {\n        for layer in additionalLayers {\n            print(layer)\n            layer.removeAllAnimations()\n            layer.removeFromSuperlayer()\n        }\n    }\n\n    // Called at each new video\n    func setupLayersForVideo(video: AerialVideo, player: AVPlayer) {\n        // We first setup all the regular layers, this will fill up the margin information\n        // and act as a preflight so we can calculate how to wrap things for long location layer text\n        for layer in additionalLayers where !(layer is LocationLayer) {\n            layer.setupForVideo(video: video, player: player)\n        }\n\n        // And only last the Location layer !\n        for layer in additionalLayers where layer is LocationLayer {\n            layer.setupForVideo(video: video, player: player)\n        }\n    }\n\n    // This is called if a screen changes resolution\n    // Can possibly happen when a new screen is connected/disconnected\n    func setContentScale(scale: CGFloat) {\n        for layer in additionalLayers {\n            layer.contentsScale = scale\n            layer.setContentScale(scale: scale)\n        }\n    }\n\n    // We use this to fully redraw all layers in a given corner\n    // This is used by transient layers, like location information that's only shown\n    // for a predefined amount of time\n    func redrawCorner(corner: InfoCorner) {\n        // first clear the offset on that corner\n        offsets.corner[corner] = 0\n\n        // Then move all our layers on that corner\n        for layer in additionalLayers {\n            if let layerCorner = layer.currentCorner {\n                if layerCorner == corner {\n                    layer.move(toCorner: corner, fullRedraw: true)\n                }\n            }\n        }\n    }\n    \n    // This is called when our view gets resized. In theory this is limited to Companion but who knows\n    func redrawAllCorners() {\n        InfoCorner.allCases.forEach { corner in\n            redrawCorner(corner: corner)\n        }\n    }\n\n    // Do we allow a random description in a corner or not ?\n    // This is a best effort to try and avoid overlaps,\n    // but it's not 100% depending on font choices\n    func isCornerAcceptable(corner: Int) -> Bool {\n        // Not the prettiest helper, this is a bit of a hack\n\n        // If we have something in both topCenter and bottomCenter, we could infinite loop\n        // So as a precaution we allow whatever was picked\n        for layer in additionalLayers where layer.corner == .topCenter {\n            for layer2 in additionalLayers where layer2.corner == .bottomCenter {\n                return true\n            }\n        }\n\n        // If we have something topCenter, never allow random on top left/right\n        if corner == 0 || corner == 2 {\n            for layer in additionalLayers where layer.corner == .topCenter {\n                return false\n            }\n        }\n\n        // Same thing on the bottom\n        if corner == 3 || corner == 5 {\n            for layer in additionalLayers where layer.corner == .bottomCenter {\n                return false\n            }\n        }\n\n        // And never allow center if there's something in a corner\n        // this one is a bit drastic as overlap isn't guaranteed but...\n        if corner == 1 {\n            for layer in additionalLayers where layer.corner == .topLeft\n                || layer.corner == .topRight {\n                return false\n            }\n        }\n\n        // And same at the bottom\n        if corner == 4 {\n            for layer in additionalLayers where layer.corner == .bottomLeft\n                || layer.corner == .bottomRight {\n                return false\n            }\n        }\n\n        return true\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Views/Layers/LayerOffsets.swift",
    "content": "//\n//  LayerOffsets.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 11/12/2019.\n//  Copyright © 2019 Guillaume Louel. All rights reserved.\n//\n\nimport Foundation\n\nclass LayerOffsets {\n    var corner = [InfoCorner: CGFloat]()\n    var maxWidth = [InfoCorner: CGFloat]()\n    init() {\n        corner[.topLeft] = 0\n        corner[.topCenter] = 0\n        corner[.topRight] = 0\n        corner[.bottomLeft] = 0\n        corner[.bottomCenter] = 0\n        corner[.bottomRight] = 0\n        corner[.screenCenter] = 0\n        corner[.absTopRight] = 0\n\n        maxWidth[.topLeft] = 0\n        maxWidth[.topCenter] = 0\n        maxWidth[.topRight] = 0\n        maxWidth[.bottomLeft] = 0\n        maxWidth[.bottomCenter] = 0\n        maxWidth[.bottomRight] = 0\n        maxWidth[.screenCenter] = 0\n        maxWidth[.absTopRight] = 0\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Views/Layers/LocationLayer.swift",
    "content": "//\n//  LocationLayer.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 11/12/2019.\n//  Copyright © 2019 Guillaume Louel. All rights reserved.\n//\n\nimport Foundation\nimport AVKit\n\nclass LocationLayer: AnimationTextLayer {\n    var config: PrefsInfo.Location?\n    var timeObserver: Any?\n\n    override init(layer: Any) {\n        super.init(layer: layer)\n    }\n\n    required init?(coder: NSCoder) {\n        fatalError(\"init(coder:) has not been implemented\")\n    }\n\n    // Our inits\n    override init(withLayer: CALayer, isPreview: Bool, offsets: LayerOffsets, manager: LayerManager) {\n        super.init(withLayer: withLayer, isPreview: isPreview, offsets: offsets, manager: manager)\n    }\n\n    convenience init(withLayer: CALayer, isPreview: Bool, offsets: LayerOffsets, manager: LayerManager, config: PrefsInfo.Location) {\n        self.init(withLayer: withLayer, isPreview: isPreview, offsets: offsets, manager: manager)\n        self.config = config\n\n        // Set our layer's font & corner now\n        (self.font, self.fontSize) = getFont(name: config.fontName,\n                                             size: config.fontSize)\n        self.corner = config.corner\n    }\n\n    // We need to clear our callbacks on the player\n    override func clear(player: AVPlayer) {\n        if timeObserver != nil {\n            player.removeTimeObserver(timeObserver!)\n            timeObserver = nil\n        }\n    }\n\n    // Called at each new video\n    override func setupForVideo(video: AerialVideo, player: AVPlayer) {\n        let poiStringProvider = PoiStringProvider.sharedInstance\n        // We need to make sure we actually have descriptions to show.\n        // Custom videos, and earlier tvOS videos may not\n        if poiStringProvider.hasPoiKeys(video: video) {\n            // Grab a sorted array of timestamps and the keys\n            let (keys, times) = getKeysAndTimestamps(video: video)\n\n            // Animate the very first one on it's own\n            var initialKey = keys[\"0\"]!\n            // Oh Apple... This is a temporary fix for Coit Tower Night where a key was reused\n            if initialKey == \"A004_C012_0\" && video.id == \"b6-4\" {\n                initialKey = \"A004_C012_100\"\n            }\n\n            let str = poiStringProvider.getString(key: initialKey, video: video)\n\n            let duration = calculateAnimationDuration(times: times, current: times[0], video: video)\n            let fadeAnimation = createFadeInOutAnimation(duration: duration)\n\n            update(string: str)\n            add(fadeAnimation, forKey: \"textfade\")\n\n            // AVPlayer requires NSValues of CMTime\n            var timevals = [NSValue]()\n            for time in times {\n                timevals.append(NSValue(time: time))\n            }\n\n            // We then callback for each timestamp\n            timeObserver = player.addBoundaryTimeObserver(forTimes: timevals, queue: DispatchQueue.main) {\n                // find closest timestamp to when we're waking up\n                var closest = 1000.0\n                var closestTime = CMTime.zero\n\n                for time in times {\n                    let ts = time.seconds\n                    let distance = abs(ts - player.currentTime().seconds)\n                    if distance < closest {\n                        closest = distance\n                        closestTime = time\n                    }\n                }\n\n                // Get the string for the current timestamp\n                let key = String(format: \"%.0f\", closestTime.seconds)\n                let str = poiStringProvider.getString(key: keys[key]!, video: video)\n\n                let duration = self.calculateAnimationDuration(times: times, current: closestTime, video: video)\n                let fadeAnimation = self.createFadeInOutAnimation(duration: duration)\n\n                self.update(string: str)\n                self.add(fadeAnimation, forKey: \"textfade\")\n            }\n        } else {\n            // We don't have any extended description, using Secondary name (location) or video name (City)\n            let str: String\n            if video.secondaryName != \"\" {\n                str = video.secondaryName\n            } else {\n                str = video.name\n            }\n\n            let duration = self.calculateAnimationDuration(times: [], current: CMTime.zero, video: video)\n            let fadeAnimation = self.createFadeInOutAnimation(duration: duration)\n\n            update(string: str)\n            add(fadeAnimation, forKey: \"textfade\")\n        }\n    }\n\n    // MARK: - Time helpers\n\n    func getKeysAndTimestamps(video: AerialVideo) -> ([String: String], [CMTime]) {\n         let poiStringProvider = PoiStringProvider.sharedInstance\n\n         // Collect all the timestamps and keys from the JSON\n         // They are store as [Time, Key]\n         let keys = poiStringProvider.getPoiKeys(video: video)\n\n         var times = [CMTime]()\n         for pkv in keys {\n             let timeStamp = Double(pkv.key)!\n             times.append(CMTime(seconds: timeStamp, preferredTimescale: 1))\n         }\n\n         // The JSON isn't sorted though, so we fix that\n         times.sort(by: { $0.seconds < $1.seconds })\n\n         return (keys, times)\n     }\n\n     func calculateAnimationDuration(times: [CMTime], current: CMTime, video: AerialVideo) -> Double {\n         // We may only show for 10s\n         if PrefsInfo.location.time == .tenSeconds {\n             return 10\n         } else {\n             if let idx = times.firstIndex(of: current) {\n                 if times.count > idx + 1 {\n                     return times[idx+1].seconds - times[idx].seconds - 1\n                 }\n             }\n\n             // We may not have a video duration, if so show it for 15 mins\n             return video.duration > 0 ? video.duration : 900\n         }\n     }\n}\n"
  },
  {
    "path": "Aerial/Source/Views/Layers/MessageLayer.swift",
    "content": "//\n//  MessageLayer.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 12/12/2019.\n//  Copyright © 2019 Guillaume Louel. All rights reserved.\n//\n\nimport Foundation\nimport AVKit\n\nclass MessageLayer: AnimationTextLayer {\n    var config: PrefsInfo.Message?\n    var wasSetup = false\n    var messageTimer: Timer?\n\n    override init(layer: Any) {\n        super.init(layer: layer)\n    }\n\n    required init?(coder: NSCoder) {\n        fatalError(\"init(coder:) has not been implemented\")\n    }\n\n    // Our inits\n    override init(withLayer: CALayer, isPreview: Bool, offsets: LayerOffsets, manager: LayerManager) {\n        super.init(withLayer: withLayer, isPreview: isPreview, offsets: offsets, manager: manager)\n\n        // We start with a full opacity\n        self.opacity = 1\n    }\n\n    convenience init(withLayer: CALayer, isPreview: Bool, offsets: LayerOffsets, manager: LayerManager, config: PrefsInfo.Message) {\n        self.init(withLayer: withLayer, isPreview: isPreview, offsets: offsets, manager: manager)\n        self.config = config\n\n        // Set our layer's font & corner now\n        (self.font, self.fontSize) = getFont(name: config.fontName,\n                                             size: config.fontSize)\n        self.corner = config.corner\n    }\n\n    override func setupForVideo(video: AerialVideo, player: AVPlayer) {\n        guard let config = config else {\n            return\n        }\n\n        // Only run this once, if enabled\n        if !wasSetup {\n            wasSetup = true\n\n            switch config.messageType {\n            case .text:\n                update(string: config.message)\n            case .shell:\n                update(string: \"\")\n                DispatchQueue.global().async {\n                    debugLog(\"setting up initial\")\n                    let result = self.runShell()\n                    \n                    if let result = result {\n                        // Do it on the main queue...\n                        DispatchQueue.main.async {\n                            debugLog(\"updating initial \" + result)\n                            self.update(string: result)\n                        }\n                    }\n                }\n                //setupRefresh()\n            case .textfile:\n                // TODO\n                update(string: config.message)\n            }\n\n            let fadeAnimation = self.createFadeInAnimation()\n            add(fadeAnimation, forKey: \"textfade\")\n        }\n    }\n\n    func setupRefresh() {\n        debugLog(\"setting up refresh\")\n        guard let config = config else {\n            return\n        }\n\n        guard config.refreshPeriodicity != .never else {\n            return\n        }\n\n        if #available(OSX 10.12, *) {\n            var interval = 0.0\n            switch config.refreshPeriodicity {\n            case .never:\n                interval = 1\n            case .tenseconds:\n                interval = 10\n            case .thirtyseconds:\n                interval = 30\n            case .oneminute:\n                interval = 60\n            case .fiveminutes:\n                interval = 300\n            case .tenminutes:\n                interval = 600\n            }\n\n            messageTimer = Timer.scheduledTimer(withTimeInterval: interval, repeats: true, block: { [self] (_) in\n\n                DispatchQueue.global().async {\n                    let result = self.runShell()\n                    self.update(string: result ?? \"\")\n                }\n            })\n        }\n    }\n\n    func runShell() -> String? {\n        guard let config = config else {\n            return nil\n        }\n\n        if config.shellScript != \"\" {\n            if FileManager.default.fileExists(atPath: PrefsInfo.message.shellScript) {\n                var result: String?\n                \n                if #available(macOS 14.0, *) {\n                    (result, _) = Aerial.helper.shell(executableURL: PrefsInfo.message.shellScript)\n                } else {\n                    (result, _) = Aerial.helper.shell(launchPath: PrefsInfo.message.shellScript)\n                }\n\n                debugLog(\"result \" + (result ?? \"\"))\n                if let res = result {\n                    return res\n                }\n            }\n        }\n\n        return nil\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Views/Layers/Music/ArtworkLayer.swift",
    "content": "//\n//  ArtworkLayer.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 30/06/2021.\n//  Copyright © 2021 Guillaume Louel. All rights reserved.\n//\n\nimport Cocoa\nimport Foundation\n\nclass ArtworkLayer: CALayer {\n    var defaultImg: NSImage?\n    override init() {\n        super.init()\n\n        if #available(macOS 11.0, *) {\n            let size: CGFloat = 200\n\n            if let image = NSImage(systemSymbolName: \"music.note\", accessibilityDescription: \"music.note\") {\n                image.isTemplate = true\n\n                // return image\n                let config = NSImage.SymbolConfiguration(pointSize: size, weight: .regular)\n                let img = image.withSymbolConfiguration(config)?.tinting(with: .white)\n\n                if let img = img {\n                    frame.size.height = size\n                    frame.size.width = size\n                    contents = img\n                    defaultImg = img\n                }\n            }\n        }\n\n    }\n\n    override init(layer: Any) {\n        super.init(layer: layer)\n    }\n\n    required init?(coder: NSCoder) {\n        fatalError(\"init(coder:) has not been implemented\")\n    }\n\n    \n    func updateArtwork(artwork: NSImage?) {\n        if let artwork = artwork {\n            contents = artwork\n        }\n    }\n    \n    /*\n    func updateArtwork(id: String) {\n        Music.instance.getArtworkUrl(id: id) { [self] artworkUrl in\n            guard let artworkUrl = artworkUrl else {\n                debugLog(\"no url found\")\n                if let defaultImg = defaultImg {\n                    contents = defaultImg\n                }\n                return\n            }\n\n            print(artworkUrl)\n\n            // Then grab said url\n            getData(from: URL(string: artworkUrl)!) { data, _, error in\n                guard let data = data, error == nil else {\n                    if let defaultImg = defaultImg {\n                        contents = defaultImg\n                    }\n                    return\n                }\n\n                DispatchQueue.main.async() {\n                    let img = NSImage(data: data)\n                    // Update it in the main thread\n                    contents = img\n                }\n            }\n        }\n    }\n\n    func getData(from url: URL, completion: @escaping (Data?, URLResponse?, Error?) -> Void) {\n        URLSession.shared.dataTask(with: url, completionHandler: completion).resume()\n    }*/\n}\n"
  },
  {
    "path": "Aerial/Source/Views/Layers/Music/MusicLayer.swift",
    "content": "//\n//  MusicLayer.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 11/06/2021.\n//  Copyright © 2021 Guillaume Louel. All rights reserved.\n//\n\nimport Foundation\nimport AVKit\n\nclass MusicLayer: AnimationLayer {\n    var config: PrefsInfo.Music?\n    var wasSetup = false\n    var timer: Timer?\n    var startTime: Date?\n    var endTime: Date?\n\n    let artworkLayer = ArtworkLayer()\n    let nameLayer = CATextLayer()\n    let artistLayer = CATextLayer()\n    let albumLayer = CATextLayer()\n\n    override init(layer: Any) {\n        super.init(layer: layer)\n    }\n\n    required init?(coder: NSCoder) {\n        fatalError(\"init(coder:) has not been implemented\")\n    }\n\n    // Our inits\n    override init(withLayer: CALayer, isPreview: Bool, offsets: LayerOffsets, manager: LayerManager) {\n        super.init(withLayer: withLayer, isPreview: isPreview, offsets: offsets, manager: manager)\n\n        self.opacity = 0\n    }\n\n    convenience init(withLayer: CALayer, isPreview: Bool, offsets: LayerOffsets, manager: LayerManager, config: PrefsInfo.Music) {\n        self.init(withLayer: withLayer, isPreview: isPreview, offsets: offsets, manager: manager)\n        self.config = config\n\n        // Set our layer's font & corner now\n        /*(self.font, self.fontSize) = getFont(name: config.fontName,\n                                             size: config.fontSize)*/\n        self.corner = config.corner\n    }\n\n    // Called at each new video, we only setup once though !\n    override func setupForVideo(video: AerialVideo, player: AVPlayer) {\n        // Only run this once\n        if !wasSetup {\n            setupLayer()\n\n            // This is where the magic happens, we get notified if we need to display something\n            Music.instance.addCallback { [self] songInfo in\n                updateStatus(songInfo: songInfo)\n                update()\n            }\n\n            wasSetup = true\n            update()\n\n            /*\n            let fadeAnimation = self.createFadeInAnimation()\n            add(fadeAnimation, forKey: \"textfade\")*/\n        }\n\n        // We trigger the first one manually, so we get data immediately\n        debugLog(\"🎧🟧 manual triggering\")\n        Music.instance.mediaRemoteCallback(nil)\n    }\n\n    func setupLayer() {\n        addSublayer(artworkLayer)\n\n        // Song name on top\n        nameLayer.string = \"\"\n        (nameLayer.font, nameLayer.fontSize) = nameLayer.makeFont(name: PrefsInfo.music.fontName, size: PrefsInfo.music.fontSize)\n        addSublayer(nameLayer)\n\n        // Artist name below\n        artistLayer.string = \"\"\n        (artistLayer.font, artistLayer.fontSize) = artistLayer.makeFont(name: PrefsInfo.music.fontName, size: PrefsInfo.music.fontSize)\n        addSublayer(artistLayer)\n\n        // Artist name below\n        albumLayer.string = \"\"\n        (albumLayer.font, albumLayer.fontSize) = albumLayer.makeFont(name: PrefsInfo.music.fontName, size: PrefsInfo.music.fontSize)\n        addSublayer(albumLayer)\n\n        \n        // frame/position stuff\n        reframe()\n    }\n\n    func reframe() {\n        // ReRect the name & artist\n        let rect = nameLayer.calculateRect(string: nameLayer.string as! String,\n                        font: nameLayer.font as! NSFont,\n                        maxWidth: Double(layerManager.frame!.size.width))\n        nameLayer.frame = rect\n        nameLayer.contentsScale = self.contentsScale\n\n        let rect2 = artistLayer.calculateRect(string: artistLayer.string as! String,\n                                              font: artistLayer.font as! NSFont,\n                                              maxWidth: Double(layerManager.frame!.size.width))\n        artistLayer.frame = rect2\n        artistLayer.contentsScale = self.contentsScale\n\n        let rect3 = albumLayer.calculateRect(string: albumLayer.string as! String,\n                                              font: albumLayer.font as! NSFont,\n                                              maxWidth: Double(layerManager.frame!.size.width))\n        albumLayer.frame = rect3\n        albumLayer.contentsScale = self.contentsScale\n        \n        \n        artworkLayer.contentsScale = self.contentsScale\n\n        // Then calc our parent frame size\n        let textHeight = nameLayer.frame.height + artistLayer.frame.height + albumLayer.frame.height\n        let textWidth = max(nameLayer.frame.width, artistLayer.frame.width, albumLayer.frame.width)\n\n        let artworkOffset = textHeight + 20\n\n        frame.size = CGSize(width: textWidth + artworkOffset, height: textHeight)\n\n        // If we don't have any song playing, we change the height to 0\n        if (nameLayer.string as! String == \"\") && (artistLayer.string as! String == \"\") {\n            frame.size.height = 0\n        }\n\n        // Position the things\n        albumLayer.anchorPoint = CGPoint(x: 0, y: 0)\n        albumLayer.position = CGPoint(x: artworkOffset, y: 0)\n\n        nameLayer.anchorPoint = CGPoint(x: 0, y: 0)\n        nameLayer.position = CGPoint(x: artworkOffset, y: albumLayer.frame.height - 6)\n\n        artistLayer.anchorPoint = CGPoint(x: 0, y: 0)\n        artistLayer.position = CGPoint(x: artworkOffset, y: albumLayer.frame.height + nameLayer.frame.height - 12)\n\n\n        artworkLayer.anchorPoint = CGPoint(x: 0, y: 0)\n        artworkLayer.position = CGPoint(x: 0, y: 0)\n        artworkLayer.frame.size = CGSize(width: frame.size.height, height: frame.size.height)\n    }\n\n    func updateStatus(songInfo: SongInfo) {\n        debugLog(\"🎧🟧 updateStatus\")\n\n        guard songInfo.name != \"\" else {\n            opacity = 0\n            frame.size.height = 0\n            return\n        }\n\n        opacity = 1\n        nameLayer.string = songInfo.name\n        artistLayer.string = songInfo.artist\n        albumLayer.string = songInfo.album\n        artworkLayer.updateArtwork(artwork: songInfo.artwork)\n        // frame/position stuff\n        reframe()\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Views/Layers/TimerLayer.swift",
    "content": "//\n//  TimerLayer.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 19/03/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Foundation\nimport AVKit\n\nclass TimerLayer: AnimationTextLayer {\n    var config: PrefsInfo.Timer?\n    var wasSetup = false\n    var timer: Timer?\n    var startTime: Date?\n    var endTime: Date?\n\n    override init(layer: Any) {\n        super.init(layer: layer)\n    }\n\n    required init?(coder: NSCoder) {\n        fatalError(\"init(coder:) has not been implemented\")\n    }\n\n    // Our inits\n    override init(withLayer: CALayer, isPreview: Bool, offsets: LayerOffsets, manager: LayerManager) {\n        super.init(withLayer: withLayer, isPreview: isPreview, offsets: offsets, manager: manager)\n\n        // Always on layers should start with full opacity\n        self.opacity = 1\n    }\n\n    convenience init(withLayer: CALayer, isPreview: Bool, offsets: LayerOffsets, manager: LayerManager, config: PrefsInfo.Timer) {\n        self.init(withLayer: withLayer, isPreview: isPreview, offsets: offsets, manager: manager)\n        self.config = config\n\n        // Set our layer's font & corner now\n        (self.font, self.fontSize) = getFont(name: config.fontName,\n                                             size: config.fontSize)\n        self.corner = config.corner\n    }\n\n    // Called at each new video, we only setup once though !\n    override func setupForVideo(video: AerialVideo, player: AVPlayer) {\n        // Only run this once\n        if !wasSetup {\n            wasSetup = true\n            startTime = Date()  // Now\n\n            let calendar = Calendar.current\n            let targetComponent = calendar.dateComponents([.hour, .minute, .second], from: PrefsInfo.timer.duration)\n            let timerInSeconds = targetComponent.hour! * 3600 + targetComponent.minute! * 60 + targetComponent.second!\n            endTime = startTime?.addingTimeInterval(TimeInterval(timerInSeconds))\n\n            if #available(OSX 10.12, *) {\n                timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true, block: { (_) in\n                    self.update(string: self.getTimeString())\n                })\n            }\n\n            update(string: getTimeString())\n            let fadeAnimation = self.createFadeInAnimation()\n            add(fadeAnimation, forKey: \"textfade\")\n        }\n    }\n\n    func getTimeString() -> String {\n        if #available(OSX 10.12, *) {\n            // Handle locale\n            var locale = Locale(identifier: Locale.preferredLanguages[0])\n            if PrefsAdvanced.ciOverrideLanguage != \"\" {\n                locale = Locale(identifier: PrefsAdvanced.ciOverrideLanguage)\n            }\n\n            var calendar = Calendar.current\n            calendar.locale = locale\n\n            let dateComponentsFormatter = DateComponentsFormatter()\n            dateComponentsFormatter.calendar = calendar\n\n            if config!.showSeconds {\n                dateComponentsFormatter.allowedUnits = [.hour, .minute, .second]\n                dateComponentsFormatter.maximumUnitCount = 3\n            } else {\n                dateComponentsFormatter.allowedUnits = [.hour, .minute]\n                dateComponentsFormatter.maximumUnitCount = 2\n            }\n            dateComponentsFormatter.unitsStyle = .full\n\n            if Date() > endTime! && PrefsInfo.timer.disableWhenElapsed {\n                // Disabling for next launch\n                PrefsInfo.timer.isEnabled = false\n            }\n\n            \n            if Date() > endTime! {\n                // We may show a message when the timer is elapsed\n                if PrefsInfo.timer.replaceWithMessage {\n                    return PrefsInfo.timer.customMessage\n                }\n            }\n            \n            \n            \n\n            return dateComponentsFormatter.string(from: Date(), to: endTime!) ?? \"\"\n        } else {\n            // Fallback on earlier versions\n            return \"\"\n        }\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Views/Layers/Weather/ConditionLayer.swift",
    "content": "//\n//  ConditionLayer.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 17/04/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Foundation\nimport AVKit\n\n// Vertically centered CATextLayer\nclass CAVCTextLayer: CATextLayer {\n    // REF: http://lists.apple.com/archives/quartz-dev/2008/Aug/msg00016.html\n    // CREDIT: David Hoerl - https://github.com/dhoerl\n    // USAGE: To fix the vertical alignment issue that currently exists within the CATextLayer class. Change made to the yDiff calculation.\n\n    override func draw(in context: CGContext) {\n        let height = self.bounds.size.height\n        let fontSize = self.fontSize\n        let yDiff = (height-fontSize)/2 - fontSize/10\n\n        context.saveGState()\n        context.translateBy(x: 0, y: -yDiff)\n        super.draw(in: context)\n        context.restoreGState()\n    }\n}\n\nclass ConditionLayer: CALayer {\n    var condition: OWeather?\n\n    init(condition: OWeather, scale: CGFloat) {\n        self.condition = condition\n        super.init()\n\n        // backgroundColor = .init(gray: 0.2, alpha: 0.2)\n\n        contentsScale = scale\n\n        // First we make the temperatures block (accurate and feels like)\n        let tempBlock = makeTemperatureBlock()\n        let feelsBlock = makeFeelsLikeBlock()\n\n        var cityNameBlock: CALayer\n        if PrefsInfo.weather.showCity {\n            cityNameBlock = makeCityNameBlock()\n        } else {\n            cityNameBlock = CALayer()\n        }\n\n        // We make the symbol a square of the combined height of both blocks\n        let combinedHeight = tempBlock.frame.height + feelsBlock.frame.height\n\n        // Create a symbol that fits the size\n        let imglayer = ConditionSymbolLayer(weather: condition.weather![0],\n                                            dt: condition.dt!,\n                                            sunrise: condition.sys!.sunrise,\n                                            sunset: condition.sys!.sunset,\n                                            size: Int(combinedHeight))\n\n        // Add the Wind layer\n        var windHeight: CGFloat = 0\n        if PrefsInfo.weather.showWind || PrefsInfo.weather.showHumidity {\n            windHeight = addWindAndHumidity(x: (imglayer.frame.width + combinedHeight/10 + tempBlock.frame.width) / 2, y: cityNameBlock.frame.height)\n        }\n\n        imglayer.anchorPoint = CGPoint(x: 0, y: 0)\n        imglayer.position = CGPoint(x: 0, y: windHeight + cityNameBlock.frame.height)\n        self.addSublayer(imglayer)\n\n        frame.size = CGSize(width: imglayer.frame.width + combinedHeight/10 + tempBlock.frame.width,\n                            height: tempBlock.frame.height + feelsBlock.frame.height + windHeight + cityNameBlock.frame.height)\n\n        addSublayer(cityNameBlock)\n        cityNameBlock.anchorPoint = CGPoint(x: 0.5, y: 0)\n        cityNameBlock.position = CGPoint(x: frame.size.width/2, y: 0)\n\n        addSublayer(tempBlock)\n        tempBlock.anchorPoint = CGPoint(x: 1, y: 1)\n        tempBlock.position = CGPoint(x: frame.size.width,\n                                     y: tempBlock.frame.height + feelsBlock.frame.height + windHeight + cityNameBlock.frame.height)\n\n        addSublayer(feelsBlock)\n        feelsBlock.anchorPoint = CGPoint(x: 0.5, y: 0)\n        feelsBlock.position = CGPoint(x: imglayer.frame.width + combinedHeight/10 + tempBlock.frame.width/2,\n                                      y: windHeight + cityNameBlock.frame.height)\n\n    }\n\n    override init(layer: Any) {\n        super.init(layer: layer)\n    }\n\n    required init?(coder: NSCoder) {\n        fatalError(\"init(coder:) has not been implemented\")\n    }\n\n    func makeCityNameBlock() -> CATextLayer {\n        let temp = CATextLayer()\n        temp.isWrapped = true\n        temp.string = condition!.name\n        (temp.font, temp.fontSize) = temp.makeFont(name: PrefsInfo.weather.fontName, size: PrefsInfo.weather.fontSize/1.5)\n        temp.alignmentMode = .center\n        // ReRect the temperature\n        let rect = temp.calculateRect(string: temp.string as! String, font: temp.font as! NSFont, maxWidth: 220)\n        temp.frame = rect\n\n        temp.contentsScale = self.contentsScale\n\n        return temp\n    }\n\n    func makeTemperatureBlock() -> CATextLayer {\n        let temp = CAVCTextLayer()\n\n        // First we start with the real temperature\n        // We keep the decimal for now on celcius, this may become optional\n        if PrefsInfo.weather.degree == .celsius {\n            temp.string = \"\\(condition!.main!.temp)°\"\n        } else {\n            temp.string = \"\\(Int(condition!.main!.temp))°\"\n        }\n\n        (temp.font, temp.fontSize) = temp.makeFont(name: PrefsInfo.weather.fontName, size: PrefsInfo.weather.fontSize)\n\n        // ReRect the temperature\n        let rect = temp.calculateRect(string: temp.string as! String, font: temp.font as! NSFont)\n        temp.frame = rect\n        temp.contentsScale = self.contentsScale\n\n        return temp\n    }\n\n    func makeFeelsLikeBlock() -> CATextLayer {\n        // Make a vertically centered layer for t°\n        let feel = CAVCTextLayer()\n        if PrefsInfo.weather.degree == .celsius {\n            feel.string = \"(\\(condition!.main!.feelsLike)°)\"\n        } else {\n            feel.string = \"(\\(Int(condition!.main!.feelsLike))°)\"\n        }\n\n        feel.contentsScale = self.contentsScale\n        (feel.font, feel.fontSize) = feel.makeFont(name: PrefsInfo.weather.fontName, size: PrefsInfo.weather.fontSize/2.2)\n\n        // ReRect the temperature\n        let rect2 = feel.calculateRect(string: feel.string as! String, font: feel.font as! NSFont)\n        feel.frame = rect2\n\n        return feel\n    }\n\n    // swiftlint:disable:next identifier_name\n    func addWindAndHumidity(x: CGFloat, y: CGFloat) -> CGFloat {\n        // We need to make sure we have the data, and the options are selected\n        var addWind = false, addHumidity = false\n\n        let wind = condition?.wind\n        let humidity = condition?.main?.humidity\n\n        if PrefsInfo.weather.showWind && wind != nil {\n            addWind = true\n        }\n        if PrefsInfo.weather.showHumidity && humidity != nil {\n            addHumidity = true\n        }\n\n        // If we shouldn't display/should and don't have data\n        if !addWind && !addHumidity {\n            return 0\n        }\n\n        // Ughhhhh, this code is so ugly\n        var windBlock: CALayer?\n        var humidityBlock: CALayer?\n\n        if addWind {\n            windBlock = makeWindBlock(wind: wind!)\n            // windBlock!.anchorPoint = CGPoint(x: 0, y: 0)\n        }\n        if addHumidity {\n            humidityBlock = makeHumidityBlock(humidity: humidity!)\n            // humidityBlock!.anchorPoint = CGPoint(x: 0, y: 0)\n        }\n\n        // Haaaaaaaa I hate this\n        if addWind && addHumidity {\n            let halfTotalWidth = (windBlock!.frame.size.width\n                            + humidityBlock!.frame.size.width)/2\n\n            windBlock!.position = CGPoint(x: x - halfTotalWidth + windBlock!.frame.size.width/2, y: y)\n            humidityBlock!.position = CGPoint(x: x + halfTotalWidth - humidityBlock!.frame.size.width/2, y: y)\n\n            self.addSublayer(windBlock!)\n            self.addSublayer(humidityBlock!)\n\n            return windBlock!.frame.height\n        } else if addWind {\n            windBlock!.position = CGPoint(x: x, y: y)\n\n            self.addSublayer(windBlock!)\n\n            return windBlock!.frame.height\n        } else if addHumidity {\n            humidityBlock!.position = CGPoint(x: x, y: y)\n\n            self.addSublayer(humidityBlock!)\n\n            return humidityBlock!.frame.height\n        }\n\n        // tmp\n        return 0\n    }\n\n    func makeHumidityBlock(humidity: Double) -> CALayer {\n        let humidityBlock = CALayer()\n\n        // Make a vertically centered layer for t°\n        let textHumidity = CAVCTextLayer()\n        textHumidity.string = \" \\(Int(humidity))%\"\n\n        // Get something large first\n        (textHumidity.font, textHumidity.fontSize) = textHumidity.makeFont(name: PrefsInfo.weather.fontName, size: PrefsInfo.weather.fontSize/2.2)\n\n        textHumidity.contentsScale = self.contentsScale\n\n        // ReRect the temperature\n        let rect2 = textHumidity.calculateRect(string: textHumidity.string as! String, font: textHumidity.font as! NSFont)\n        textHumidity.frame = rect2\n        textHumidity.contentsScale = self.contentsScale\n\n        humidityBlock.addSublayer(textHumidity)\n\n        let imglayer = Aerial.helper.getSymbolLayer(\"humidity\", size: CGFloat(PrefsInfo.weather.fontSize/2.8))\n\n        // We put the temperature at the right of the wind icon\n        textHumidity.anchorPoint = CGPoint(x: 0, y: 0)\n        textHumidity.position = CGPoint(x: imglayer.frame.height, y: 0)\n\n        imglayer.anchorPoint = CGPoint(x: 0.5, y: 0.5)\n        imglayer.position = CGPoint(x: imglayer.frame.height/2,\n                                    y: textHumidity.frame.height/2)\n\n        imglayer.contentsScale = self.contentsScale\n        humidityBlock.frame.size = CGSize(width: textHumidity.frame.width+imglayer.frame.width,\n                                          height: max(textHumidity.frame.height, imglayer.frame.height))\n\n        humidityBlock.anchorPoint = CGPoint(x: 0.5, y: 0)\n        humidityBlock.addSublayer(imglayer)\n        return humidityBlock\n    }\n\n    func makeWindBlock(wind: OWWind) -> CALayer {\n        let windBlock = CALayer()\n\n        // Make a vertically centered layer for t°\n        let textWind = CAVCTextLayer()\n        if PrefsInfo.weather.degree == .celsius {\n            if PrefsInfo.weatherWindMode == .kph {\n                textWind.string = \"\\(Int(wind.speed * 3.6)) km/h\"\n            } else {\n                textWind.string = \"\\(Int(wind.speed)) m/s\"\n            }\n        } else {\n            textWind.string = \"\\(Int(wind.speed)) mph\"\n        }\n\n        // Get something large first\n        (textWind.font, textWind.fontSize) = textWind.makeFont(name: PrefsInfo.weather.fontName, size: PrefsInfo.weather.fontSize/2.2)\n\n        textWind.contentsScale = self.contentsScale\n\n        // ReRect the temperature\n        let rect2 = textWind.calculateRect(string: textWind.string as! String, font: textWind.font as! NSFont)\n        textWind.frame = rect2\n        textWind.contentsScale = self.contentsScale\n\n        windBlock.addSublayer(textWind)\n\n        // Create the wind indicator\n        let imglayer = WindDirectionLayer(direction: 225, size: CGFloat(PrefsInfo.weather.fontSize/2.8))\n\n        textWind.anchorPoint = CGPoint(x: 0, y: 0)\n        textWind.position = CGPoint(x: imglayer.frame.height, y: 0)\n\n        // Rotation is relative to anchorpoint, so it has to be middle\n        imglayer.anchorPoint = CGPoint(x: 0.5, y: 0.5)\n        imglayer.position = CGPoint(x: imglayer.frame.height/2, y: textWind.frame.height/2)\n\n        // Rotation is done here\n        imglayer.transform = CATransform3DMakeRotation(CGFloat((180 + wind.deg)) / 180.0 * .pi, 0.0, 0.0, -1.0)\n\n        imglayer.contentsScale = self.contentsScale\n\n        windBlock.frame.size = CGSize(width: textWind.frame.width+imglayer.frame.width,\n                                      height: max(textWind.frame.height, imglayer.frame.height))\n        windBlock.addSublayer(imglayer)\n        windBlock.anchorPoint = CGPoint(x: 0.5, y: 0)\n\n        return windBlock\n    }\n\n}\n"
  },
  {
    "path": "Aerial/Source/Views/Layers/Weather/ConditionSymbolLayer.swift",
    "content": "//\n//  ConditionSymbolLayer.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 24/04/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Cocoa\nimport Foundation\n\nclass ConditionSymbolLayer: CALayer {\n    let mainSymbols = [200: \"cloud.bolt.rain\",\n                       201: \"cloud.bolt.rain\",\n                       202: \"cloud.bolt.rain\",\n                       210: \"cloud.sun.bolt\",\n                       211: \"cloud.bolt\",\n                       212: \"cloud.bolt\",\n                       221: \"cloud.bolt\",\n                       230: \"cloud.bolt.rain\",\n                       231: \"cloud.bolt.rain\",\n                       232: \"cloud.bolt.rain\",\n\n                       300: \"cloud.drizzle\",\n                       301: \"cloud.drizzle\",\n                       302: \"cloud.drizzle\",\n                       310: \"cloud.drizzle\",\n                       311: \"cloud.drizzle\",\n                       312: \"cloud.drizzle\",\n                       313: \"cloud.drizzle\",\n                       314: \"cloud.drizzle\",\n                       321: \"cloud.drizzle\",\n\n                       500: \"cloud.sun.rain\",\n                       501: \"cloud.rain\",\n                       502: \"cloud.heavyrain\",\n                       503: \"cloud.heavyrain\",\n                       504: \"cloud.heavyrain\",\n\n                       511: \"cloud.sleet\",\n\n                       520: \"cloud.rain\",\n                       521: \"cloud.rain\",\n                       522: \"cloud.heavyrain\",\n                       531: \"cloud.rain\",\n\n                       600: \"snow\",\n                       601: \"snow\",\n                       602: \"cloud.snow\",\n\n                       611: \"cloud.sleet\",\n                       612: \"cloud.sleet\",\n                       613: \"cloud.sleet\",\n                       615: \"cloud.sleet\",\n                       616: \"cloud.sleet\",\n\n                       620: \"snow\",\n                       621: \"snow\",\n                       622: \"cloud.snow\",\n\n                       701: \"sun.haze\",\n                       711: \"smoke\",\n                       721: \"sun.haze\",\n                       731: \"sun.dust\",\n                       741: \"sun.haze\",\n                       751: \"sun.dust\",\n                       761: \"sun.dust\",\n                       762: \"sun.dust\",\n                       781: \"tornado\",\n\n                       800: \"sun.max\",\n                       801: \"sun.max\",\n                       802: \"cloud.sun\",\n                       803: \"cloud.sun\",\n                       804: \"cloud\" ]//\n\n    let nightSymbols = [210: \"cloud.moon.bolt\",\n\n                        500: \"cloud.moon.rain\",\n\n                        800: \"moon.stars\",\n                        801: \"moon\",\n                        802: \"cloud.moon\",\n                        803: \"cloud.moon\" ]\n\n    init(weather: OWWeather, dt: Int, isNight: Bool, size: Int, square: Bool = false) {\n        super.init()\n\n        var img: NSImage?\n\n        switch PrefsInfo.weather.icons {\n        case .flat:\n            img = makeSymbol(name: getSymbol(condition: weather.id,\n                                                 isNight: isNight), size: size)\n        case .colorflat:\n            img = makeColorSymbol(name: getColorSymbol(condition: weather.id,\n                                                  isNight: isNight), size: size)\n        case .oweather:\n            downloadImage(from: URL(string: \"https://openweathermap.org/img/wn/\\(weather.icon)@4x.png\")!, size: size)\n            img = nil\n        }\n\n        if let img = img {\n            if !square {\n                frame.size.height = CGFloat(size)\n                frame.size.width = CGFloat(size) * img.size.width / img.size.height\n            } else {\n                if frame.size.height > frame.size.width {\n                    frame.size.height = CGFloat(size)\n                    frame.size.width = CGFloat(size) * img.size.width / img.size.height\n                } else {\n                    frame.size.width = CGFloat(size)\n                    frame.size.height = CGFloat(size) * img.size.height / img.size.width\n                }\n            }\n\n            contents = img\n        }\n    }\n\n    init(weather: OWWeather, dt: Int, sunrise: Int, sunset: Int, size: Int, square: Bool = false) {\n        super.init()\n\n        // In case icons are updated, it's important to test them !\n        // test()\n\n        let isNight = isNight(dt: dt, sunrise: sunrise, sunset: sunset)\n        var img: NSImage?\n\n        switch PrefsInfo.weather.icons {\n        case .flat:\n            img = makeSymbol(name: getSymbol(condition: weather.id,\n                                                 isNight: isNight), size: size)\n        case .colorflat:\n            img = makeColorSymbol(name: getColorSymbol(condition: weather.id,\n                                                  isNight: isNight), size: size)\n        case .oweather:\n            downloadImage(from: URL(string: \"https://openweathermap.org/img/wn/\\(weather.icon)@4x.png\")!, size: size)\n            img = nil\n        }\n\n        if let img = img {\n            if !square {\n                frame.size.height = CGFloat(size)\n                frame.size.width = CGFloat(size) * img.size.width / img.size.height\n            } else {\n                if frame.size.height > frame.size.width {\n                    frame.size.height = CGFloat(size)\n                    frame.size.width = CGFloat(size) * img.size.width / img.size.height\n                } else {\n                    frame.size.width = CGFloat(size)\n                    frame.size.height = CGFloat(size) * img.size.height / img.size.width\n                }\n            }\n\n            contents = img\n        }\n    }\n\n    override init(layer: Any) {\n        super.init(layer: layer)\n    }\n\n    required init?(coder: NSCoder) {\n        fatalError(\"init(coder:) has not been implemented\")\n    }\n\n    func makeSymbol(name: String, size: Int) -> NSImage? {\n        if #available(macOS 11.0, *) {\n            if let image = NSImage(systemSymbolName: name, accessibilityDescription: name) {\n                image.isTemplate = true\n\n                // return image\n                let config = NSImage.SymbolConfiguration(pointSize: CGFloat(size), weight: .regular)\n                return image.withSymbolConfiguration(config)?.tinting(with: .white)\n            }\n        } else {\n            // We fallback on the pdf icons\n            let imagePath = Bundle(for: PanelWindowController.self).path(\n                forResource: name, ofType: \"pdf\") ?? \"\"\n\n            let img = NSImage(contentsOfFile: imagePath)\n\n            return img\n        }\n\n        return nil\n    }\n\n    func makeColorSymbol(name: String, size: Int) -> NSImage? {\n        if #available(macOS 11.0, *) {\n            if let image = NSImage(systemSymbolName: name, accessibilityDescription: name) {\n                image.isTemplate = false\n\n                // return image\n                let config = NSImage.SymbolConfiguration(pointSize: CGFloat(size), weight: .regular)\n                return image.withSymbolConfiguration(config) // ?.tinting(with: .white)\n            }\n        }\n\n        return nil\n    }\n\n    func getData(from url: URL, completion: @escaping (Data?, URLResponse?, Error?) -> Void) {\n        URLSession.shared.dataTask(with: url, completionHandler: completion).resume()\n    }\n\n    func downloadImage(from url: URL, size: Int) {\n        frame.size.height = CGFloat(size)\n        frame.size.width = CGFloat(size)\n\n        getData(from: url) { data, _, error in\n            guard let data = data, error == nil else { return }\n\n            DispatchQueue.main.async() {\n                let img = NSImage(data: data)\n                self.contents = img\n\n                /*\n                // If we have something, trim and put it up\n                if let img = imgs {\n                    // Get the trimmed image first, goes on the left\n                    let trimmedimg = img.trim()!\n\n                    let imglayer = CALayer()\n                    imglayer.frame.size.height = trimmedimg.size.height / 2\n                    imglayer.frame.size.width = trimmedimg.size.width / 2\n                    imglayer.contents = trimmedimg\n\n                    imglayer.anchorPoint = CGPoint(x: 0, y: 0.5)\n                    imglayer.position = CGPoint(x: 0, y: 50)\n                    self.addSublayer(imglayer)\n\n                    let tempWidth = self.addTemperature(at: imglayer.frame.width + 15)\n                    self.addFeelsLike(at: imglayer.frame.width + 15 + (tempWidth / 2))\n                    self.addWind(at: (imglayer.frame.width + 15 + tempWidth) / 2)\n\n                    // Set the final size\n                    self.frame.size = CGSize(width: imglayer.frame.width + 15 + tempWidth, height: 75)\n                }\n                 */\n            }\n        }\n    }\n\n    func test() {\n        nightSymbols.forEach { (key: Int, value: String) in\n            let imagePath = Bundle(for: PanelWindowController.self).path(\n            forResource: getSymbol(condition: key, isNight: true),\n            ofType: \"pdf\")\n            if imagePath == nil {\n                debugLog(\"ERROR night \\(key) \\(value)\")\n            } else {\n                debugLog(\"OK night \\(key) \\(value)\")\n            }\n        }\n\n        mainSymbols.forEach { (key: Int, value: String) in\n            let imagePath = Bundle(for: PanelWindowController.self).path(\n            forResource: getSymbol(condition: key, isNight: true),\n            ofType: \"pdf\")\n            if imagePath == nil {\n                debugLog(\"ERROR day \\(key) \\(value)\")\n            } else {\n                debugLog(\"OK day \\(key) \\(value)\")\n            }\n        }\n\n    }\n\n    func getSymbol(condition: Int, isNight: Bool) -> String {\n        if isNight && nightSymbols[condition] != nil {\n            return nightSymbols[condition]!\n        } else {\n            if mainSymbols[condition] != nil {\n                return mainSymbols[condition]!\n            } else {\n                return \"wrench\"\n            }\n        }\n    }\n\n    func getColorSymbol(condition: Int, isNight: Bool) -> String {\n        let regular = getSymbol(condition: condition, isNight: isNight)\n\n        if regular != \"wrench\" && regular != \"snow\" && regular != \"tornado\" {\n            return regular + \".fill\"\n        } else {\n            return regular\n        }\n    }\n\n    func isNight(dt: Int, sunrise: Int, sunset: Int) -> Bool {\n        if dt < sunrise || dt > sunset {\n            return true\n        } else {\n            return false\n        }\n    }\n\n}\n"
  },
  {
    "path": "Aerial/Source/Views/Layers/Weather/ForecastLayer.swift",
    "content": "//\n//  ForecastLayer.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 23/03/2021.\n//  Copyright © 2021 Guillaume Louel. All rights reserved.\n//\n\nimport Foundation\nimport AVKit\n\n// swiftlint:disable:next type_body_length\nclass ForecastLayer: CALayer {\n    var condition: ForecastElement?\n\n    // swiftlint:disable:next cyclomatic_complexity\n    init(condition: ForecastElement, scale: CGFloat) {\n        self.condition = condition\n        super.init()\n\n        // backgroundColor = .init(gray: 0.2, alpha: 0.2)\n\n        contentsScale = scale\n        let size = PrefsInfo.weather.fontSize\n\n        // We have daily forecasts, and hourly forecasts available (woo)\n        if PrefsInfo.weather.mode == .forecast3days || PrefsInfo.weather.mode == .forecast5days {\n            // How many days to display, currently we do 3 and 5\n            var days = 5\n            if PrefsInfo.weather.mode == .forecast3days {\n                days = 3\n            }\n\n            if let flist = condition.list {\n                let breakIndex = detectDayChange(list: flist)\n\n                if flist.count >= 40 {\n\n                    var height: CGFloat = 0\n                    for dayidx in 0 ..< days {\n                        let start = breakIndex + (8 * (dayidx-1))\n                        var day: CALayer\n\n                        if dayidx == 0 {\n                            day = makeDayBlock(slice: flist[0..<breakIndex], size: size*2)\n\n                        } else {\n                            day = makeDayBlock(slice: flist[start..<(start+8)], size: size*2)\n                        }\n\n                        day.anchorPoint = CGPoint(x: 0, y: 0)\n                        day.position = CGPoint(x: Int(size * 2) * dayidx, y: 0)\n                        self.addSublayer(day)\n\n                        if day.frame.height > height {\n                            height = day.frame.height\n                        }\n                    }\n\n                    let legend = makeLegendBlock(size: size*2)\n                    legend.anchorPoint = CGPoint(x: 0, y: 0)\n                    legend.position = CGPoint(x: Int(size*2) * days, y: 0)\n                    self.addSublayer(legend)\n\n                    self.frame = CGRect(x: 0, y: 0, width:\n                                            CGFloat(Double((days + 1)) * (size * 2)), height: height)\n                }\n            }\n        } else {\n            // Hourly forecast, we do 6 hours\n            if let flist = condition.list {\n                // Just in case\n                if flist.count > 5 {\n                    var height: CGFloat = 0\n\n                    for houridx in 0 ..< 6 {\n                        let day = makeHourBlock(hour: flist[houridx],\n                                                size: size*2)\n                        day.anchorPoint = CGPoint(x: 0, y: 0)\n                        day.position = CGPoint(x: Int(size * 2) * houridx, y: 0)\n                        self.addSublayer(day)\n\n                        if day.frame.height > height {\n                            height = day.frame.height\n                        }\n                    }\n\n                    let legend = makeLegendBlock(size: size*2)\n                    legend.anchorPoint = CGPoint(x: 0, y: 0)\n                    legend.position = CGPoint(x: Int(size*2) * 6, y: 0)\n                    self.addSublayer(legend)\n\n                    self.frame = CGRect(x: 0, y: 0, width:\n                                            CGFloat(7 * (size * 2)), height: height)\n                }\n            }\n        }\n    }\n\n    func detectDayChange(list: [FList]) -> Int {\n        var firstDay: String?\n        var index = 0\n        for day in list {\n            if firstDay == nil {\n                firstDay = dayStringFromTimeStamp(timeStamp: Double(day.dt!))\n            } else {\n                if firstDay != dayStringFromTimeStamp(timeStamp: Double(day.dt!)) {\n                    return index\n                }\n            }\n\n            index += 1\n        }\n\n        // fallback, uh...\n        return 1\n    }\n\n    override init(layer: Any) {\n        super.init(layer: layer)\n    }\n\n    required init?(coder: NSCoder) {\n        fatalError(\"init(coder:) has not been implemented\")\n    }\n\n    func makeDayBlock(slice: ArraySlice<FList>, size: Double) -> CALayer {\n        // This is ugly but we try and do the  best from the data we get...\n        var tmin, tmax: Double?\n        var day: Int?\n\n        let array = Array(slice)\n\n        for element in array {\n            if day == nil {\n                day = element.dt\n            }\n\n            if tmin == nil {\n                tmin = element.main!.tempMin\n            } else {\n                if element.main!.tempMin! < tmin! {\n                    tmin = element.main!.tempMin\n                }\n            }\n\n            if tmax == nil {\n                tmax = element.main!.tempMax\n            } else {\n                if element.main!.tempMax! > tmax! {\n                    tmax = element.main!.tempMax\n                }\n            }\n        }\n\n        let list = array[array.count/2]\n\n        let weather = list.weather![0]\n        let windSpeed = list.wind!.speed!\n        let windDeg = list.wind!.deg!\n        let whumidity = list.main!.humidity\n\n        let mainLayer = CALayer()\n\n        // First create the symbol\n        let imglayer = ConditionSymbolLayer(weather: weather,\n                                            dt: day!,\n                                            isNight: false,\n                                            size: Int(size),\n                                            square: true)\n\n        let windLayer = makeWindBlock(speed: windSpeed, degree: windDeg, size: size/4)\n\n        let max = CAVCTextLayer()\n        max.string = \"\\(String(format: \"%.0f\", tmax!))°\"\n\n        (max.font, max.fontSize) = max.makeFont(name: PrefsInfo.weather.fontName, size: size/4)\n\n        // ReRect the temperature\n        let rect = max.calculateRect(string: max.string as! String, font: max.font as! NSFont)\n        max.frame = rect\n        max.contentsScale = self.contentsScale\n        max.alignmentMode = .center\n\n        let min = CAVCTextLayer()\n        min.string = \"\\(String(format: \"%.0f\", tmin!))°\"\n\n        (min.font, min.fontSize) = min.makeFont(name: PrefsInfo.weather.fontName, size: size/4)\n\n        // ReRect the temperature\n        let rect2 = min.calculateRect(string: min.string as! String, font: min.font as! NSFont)\n        min.frame = rect2\n        min.contentsScale = self.contentsScale\n        min.alignmentMode = .center\n\n        let humidity = CAVCTextLayer()\n        humidity.string = \"\\(whumidity!)%\"\n\n        (humidity.font, humidity.fontSize) = humidity.makeFont(name: PrefsInfo.weather.fontName, size: size/4)\n\n        // ReRect the temperature\n        let recth = humidity.calculateRect(string: humidity.string as! String, font: humidity.font as! NSFont)\n        humidity.frame = recth\n        humidity.contentsScale = self.contentsScale\n        humidity.alignmentMode = .center\n\n        let dayi = CAVCTextLayer()\n        dayi.string = dayStringFromTimeStamp(timeStamp: Double(day!))\n\n        (dayi.font, dayi.fontSize) = dayi.makeFont(name: PrefsInfo.weather.fontName, size: size/4)\n\n        // ReRect the temperature\n        let rect4 = dayi.calculateRect(string: dayi.string as! String, font: dayi.font as! NSFont)\n        dayi.frame = rect4\n        dayi.contentsScale = self.contentsScale\n        dayi.alignmentMode = .center\n\n        // Then we draw bottom to top\n        dayi.anchorPoint = CGPoint(x: 0.5, y: 0)\n        dayi.position = CGPoint(x: size/2, y: 0)\n        mainLayer.addSublayer(dayi)\n        var offset = dayi.frame.height\n\n        if PrefsInfo.weather.showWind {\n            windLayer.anchorPoint = CGPoint(x: 0.5, y: 0)\n            windLayer.position = CGPoint(x: CGFloat(size)/2, y: offset)\n            mainLayer.addSublayer(windLayer)\n            offset += windLayer.frame.height\n        }\n\n        if PrefsInfo.weather.showHumidity {\n            humidity.anchorPoint = CGPoint(x: 0.5, y: 0)\n            humidity.position = CGPoint(x: CGFloat(size)/2, y: offset)\n            mainLayer.addSublayer(humidity)\n            offset += humidity.frame.height\n        }\n\n        min.anchorPoint = CGPoint(x: 0.5, y: 0)\n        min.position = CGPoint(x: CGFloat(size)/2, y: offset)\n        mainLayer.addSublayer(min)\n        offset += min.frame.height\n\n        max.anchorPoint = CGPoint(x: 0.5, y: 0)\n        max.position = CGPoint(x: CGFloat(size) / 2, y: offset)\n        mainLayer.addSublayer(max)\n        offset += max.frame.height\n\n        imglayer.anchorPoint = CGPoint(x: 0.5, y: 0.5)\n        imglayer.position = CGPoint(x: Double(size) / 2,\n                                    y: Double(offset) + size/2)\n        mainLayer.addSublayer(imglayer)\n\n        mainLayer.frame = CGRect(x: 0, y: 0,\n                                 width: CGFloat(size),\n                                 height: offset + imglayer.frame.height)\n        return mainLayer\n    }\n\n    func makeHourBlock(hour: FList, size: Double) -> CALayer {\n        let mainLayer = CALayer()\n\n        let isNight = hour.sys!.pod! == \"n\" ? true : false\n\n        // First create the symbol\n        let imglayer = ConditionSymbolLayer(weather: hour.weather![0],\n                                            dt: hour.dt!,\n                                            isNight: isNight,\n                                            size: Int(size),\n                                            square: true)\n\n        let windLayer = makeWindBlock(speed: hour.wind!.speed!, degree: hour.wind!.deg!, size: size/4)\n\n        let temp = CAVCTextLayer()\n        temp.string = \"\\(String(format: \"%.0f\", hour.main!.temp!))°\"\n\n        (temp.font, temp.fontSize) = temp.makeFont(name: PrefsInfo.weather.fontName, size: size/4)\n\n        // ReRect the temperature\n        let rect = temp.calculateRect(string: temp.string as! String, font: temp.font as! NSFont)\n        temp.frame = rect\n        temp.contentsScale = self.contentsScale\n        temp.alignmentMode = .center\n\n        let feelsLike = CAVCTextLayer()\n        feelsLike.string = \"\\(String(format: \"%.0f\", hour.main!.feelsLike!))°\"\n\n        (feelsLike.font, feelsLike.fontSize) = feelsLike.makeFont(name: PrefsInfo.weather.fontName, size: size/4)\n\n        // ReRect the temperature\n        let rect2 = feelsLike.calculateRect(string: feelsLike.string as! String, font: feelsLike.font as! NSFont)\n        feelsLike.frame = rect2\n        feelsLike.contentsScale = self.contentsScale\n        feelsLike.alignmentMode = .center\n\n        let humidity = CAVCTextLayer()\n        humidity.string = \"\\(hour.main!.humidity!)%\"\n\n        (humidity.font, humidity.fontSize) = humidity.makeFont(name: PrefsInfo.weather.fontName, size: size/4)\n\n        // ReRect the temperature\n        let recth = humidity.calculateRect(string: humidity.string as! String, font: humidity.font as! NSFont)\n        humidity.frame = recth\n        humidity.contentsScale = self.contentsScale\n        humidity.alignmentMode = .center\n\n        let dayi = CAVCTextLayer()\n        dayi.string = hourStringFromTimeStamp(timeStamp: Double(hour.dt!))\n\n        (dayi.font, dayi.fontSize) = dayi.makeFont(name: PrefsInfo.weather.fontName, size: size/4)\n\n        // ReRect the temperature\n        let rect4 = dayi.calculateRect(string: dayi.string as! String, font: dayi.font as! NSFont)\n        dayi.frame = rect4\n        dayi.contentsScale = self.contentsScale\n        dayi.alignmentMode = .center\n\n        // Then we draw bottom to top\n        dayi.anchorPoint = CGPoint(x: 0.5, y: 0)\n        dayi.position = CGPoint(x: size/2, y: 0)\n        mainLayer.addSublayer(dayi)\n        var offset = dayi.frame.height\n\n        if PrefsInfo.weather.showWind {\n            windLayer.anchorPoint = CGPoint(x: 0.5, y: 0)\n            windLayer.position = CGPoint(x: CGFloat(size)/2, y: offset)\n            mainLayer.addSublayer(windLayer)\n            offset += windLayer.frame.height\n        }\n\n        if PrefsInfo.weather.showHumidity {\n            humidity.anchorPoint = CGPoint(x: 0.5, y: 0)\n            humidity.position = CGPoint(x: CGFloat(size)/2, y: offset)\n            mainLayer.addSublayer(humidity)\n            offset += humidity.frame.height\n        }\n\n        feelsLike.anchorPoint = CGPoint(x: 0.5, y: 0)\n        feelsLike.position = CGPoint(x: CGFloat(size)/2, y: offset)\n        mainLayer.addSublayer(feelsLike)\n        offset += feelsLike.frame.height\n\n        temp.anchorPoint = CGPoint(x: 0.5, y: 0)\n        temp.position = CGPoint(x: CGFloat(size) / 2, y: offset)\n        mainLayer.addSublayer(temp)\n        offset += temp.frame.height\n\n        imglayer.anchorPoint = CGPoint(x: 0.5, y: 0.5)\n        imglayer.position = CGPoint(x: Double(size) / 2,\n                                    y: Double(offset) + size/2)\n        mainLayer.addSublayer(imglayer)\n\n        mainLayer.frame = CGRect(x: 0, y: 0,\n                                 width: CGFloat(size),\n                                 height: offset + imglayer.frame.height)\n        return mainLayer\n    }\n\n    func makeLegendBlock(size: Double) -> CALayer {\n        let mainLayer = CALayer()\n\n        // Make a vertically centered layer for t°\n        let windLayer = CAVCTextLayer()\n\n        if PrefsInfo.weather.degree == .celsius {\n            if PrefsInfo.weatherWindMode == .kph {\n                windLayer.string = \"km/h\"\n            } else {\n                windLayer.string = \"m/s\"\n            }\n        } else {\n            windLayer.string = \"mph\"\n        }\n\n        // Get something large first\n        (windLayer.font, windLayer.fontSize) = windLayer.makeFont(name: PrefsInfo.weather.fontName, size: size/4)\n\n        // ReRect the temperature\n        let rect2 = windLayer.calculateRect(string: windLayer.string as! String, font: windLayer.font as! NSFont)\n        windLayer.frame = rect2\n        windLayer.contentsScale = self.contentsScale\n        windLayer.alignmentMode = .center\n\n        let max = CAVCTextLayer()\n        if PrefsInfo.weather.mode == .forecast6hours {\n            max.string = \"Temperature\"\n        } else {\n            max.string = \"Max\"\n        }\n\n        (max.font, max.fontSize) = max.makeFont(name: PrefsInfo.weather.fontName, size: size/4)\n\n        // ReRect the temperature\n        let rect = max.calculateRect(string: max.string as! String, font: max.font as! NSFont)\n        max.frame = rect\n        max.contentsScale = self.contentsScale\n        max.alignmentMode = .center\n\n        let min = CAVCTextLayer()\n        min.string = \"Min\"\n        if PrefsInfo.weather.mode == .forecast6hours {\n            min.string = \"Feels Like\"\n        } else {\n            min.string = \"Min\"\n        }\n\n        (min.font, min.fontSize) = min.makeFont(name: PrefsInfo.weather.fontName, size: size/4)\n\n        // ReRect the temperature\n        let rect3 = min.calculateRect(string: min.string as! String, font: min.font as! NSFont)\n        min.frame = rect3\n        min.contentsScale = self.contentsScale\n        min.alignmentMode = .center\n\n        let humidity = CAVCTextLayer()\n        humidity.string = \"Humidity\"\n        (humidity.font, humidity.fontSize) = humidity.makeFont(name: PrefsInfo.weather.fontName, size: size/4)\n\n        // ReRect the temperature\n        let recth = humidity.calculateRect(string: humidity.string as! String, font: humidity.font as! NSFont)\n        humidity.frame = recth\n        humidity.contentsScale = self.contentsScale\n        humidity.alignmentMode = .center\n\n        // Then we draw bottom to top, we skip the first which shows the hour/day\n        var offset: CGFloat = min.frame.height\n\n        if PrefsInfo.weather.showWind {\n            windLayer.anchorPoint = CGPoint(x: 0.5, y: 0)\n            windLayer.position = CGPoint(x: CGFloat(size)/2, y: offset)\n            mainLayer.addSublayer(windLayer)\n            offset += windLayer.frame.height\n        }\n\n        if PrefsInfo.weather.showHumidity {\n            humidity.anchorPoint = CGPoint(x: 0.5, y: 0)\n            humidity.position = CGPoint(x: CGFloat(size)/2, y: offset)\n            mainLayer.addSublayer(humidity)\n            offset += humidity.frame.height\n        }\n\n        min.anchorPoint = CGPoint(x: 0.5, y: 0)\n        min.position = CGPoint(x: CGFloat(size)/2, y: offset)\n        mainLayer.addSublayer(min)\n        offset += min.frame.height\n\n        max.anchorPoint = CGPoint(x: 0.5, y: 0)\n        max.position = CGPoint(x: CGFloat(size) / 2, y: offset)\n        mainLayer.addSublayer(max)\n        // offset += max.frame.height\n\n        return mainLayer\n    }\n\n    func makeWindBlock(speed: Double, degree: Int, size: Double) -> CALayer {\n        let windLayer = CALayer()\n\n        // Make a vertically centered layer for t°\n        let wind = CAVCTextLayer()\n\n        if PrefsInfo.weatherWindMode == .kph && PrefsInfo.weather.degree == .celsius {\n            wind.string = String(format: \"%.0f\", speed * 3.6)\n        } else {\n            wind.string = String(format: \"%.0f\", speed)\n        }\n        \n        // Get something large first\n        (wind.font, wind.fontSize) = wind.makeFont(name: PrefsInfo.weather.fontName, size: size)\n\n        // ReRect the temperature\n        let rect2 = wind.calculateRect(string: wind.string as! String, font: wind.font as! NSFont)\n        wind.frame = rect2\n        wind.contentsScale = self.contentsScale\n\n        // Create the wind indicator\n        let imglayer = WindDirectionLayer(direction: 225, size: CGFloat(size/1.27))\n\n        imglayer.contentsScale = self.contentsScale\n        imglayer.transform = CATransform3DMakeRotation(CGFloat((180 + degree)) / 180.0 * .pi, 0.0, 0.0, -1.0)\n\n        imglayer.anchorPoint = CGPoint(x: 0.5, y: 0.5)\n        imglayer.position = CGPoint(x: imglayer.frame.width/2,\n                                    y: wind.frame.height/2)\n\n        windLayer.addSublayer(imglayer)\n\n        // We put the temperature at the right of the weather icon\n        wind.anchorPoint = CGPoint(x: 0, y: 0)\n        wind.position = CGPoint(x: imglayer.frame.width + 3, y: 0)\n        windLayer.addSublayer(wind)\n\n        // Reset the container frame\n        windLayer.frame = CGRect(x: 0, y: 0, width: imglayer.frame.width + wind.frame.width + 3, height: wind.frame.height)\n        return windLayer\n    }\n\n    func dayStringFromTimeStamp(timeStamp: Double) -> String {\n        let date = Date(timeIntervalSince1970: timeStamp)\n        let dateFormatter = DateFormatter()\n\n        var locale = Locale(identifier: Locale.preferredLanguages[0])\n        if PrefsAdvanced.ciOverrideLanguage != \"\" {\n            locale = Locale(identifier: PrefsAdvanced.ciOverrideLanguage)\n        }\n\n        dateFormatter.locale = locale\n        dateFormatter.dateFormat = \"E\"\n        return dateFormatter.string(from: date)\n    }\n\n    func hourStringFromTimeStamp(timeStamp: Double) -> String {\n        let date = Date(timeIntervalSince1970: timeStamp)\n        let dateFormatter = DateFormatter()\n\n        var locale = Locale(identifier: Locale.preferredLanguages[0])\n        if PrefsAdvanced.ciOverrideLanguage != \"\" {\n            locale = Locale(identifier: PrefsAdvanced.ciOverrideLanguage)\n        }\n\n        dateFormatter.locale = locale\n        dateFormatter.dateFormat = \"HH\"\n        return dateFormatter.string(from: date) + \"h\"\n    }\n}\n\nextension Double {\n    func roundTemp() -> Double {\n        if PrefsInfo.weather.degree == .celsius {\n            return self.rounded(toPlaces: 0) // rounded(toPlaces: 1)\n        } else {\n            return self.rounded()\n        }\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Views/Layers/Weather/WeatherLayer.swift",
    "content": "//\n//  WeatherLayer.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 16/04/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Foundation\nimport AVKit\n\nclass WeatherLayer: AnimationLayer {\n    var config: PrefsInfo.Weather?\n    var wasSetup = false\n    var todayCond: ConditionLayer?\n    var forecastCond: ForecastLayer?\n\n    var cscale: CGFloat?\n\n    private static let cachedWeatherURL = URL(fileURLWithPath: Cache.supportPath, isDirectory: true).appendingPathComponent(\"Weather.json\")\n    private static let cachedWeatherForecastURL = URL(fileURLWithPath: Cache.supportPath, isDirectory: true).appendingPathComponent(\"Forecast.json\")\n    private static let cachedWeatherUpdateInterval: TimeInterval = 60 * 15\n\n    var cachedWeather: OWeather? {\n        get {\n            let fm = FileManager.default\n            guard fm.fileExists(atPath: WeatherLayer.cachedWeatherURL.path) else { return nil }\n            do {\n                guard let date = try fm.attributesOfItem(atPath: WeatherLayer.cachedWeatherURL.path)[.modificationDate] as? Date else {\n                    assertionFailure(\"Couldn't get modificationDate from File System!\")\n                    return nil\n                }\n                // Make sure the cache was written in the last \"update interval\" seconds, otherwise download now\n                guard date >= Date().addingTimeInterval(-WeatherLayer.cachedWeatherUpdateInterval) else { return nil }\n                let data = try Data(contentsOf: WeatherLayer.cachedWeatherURL)\n                let result = try JSONDecoder().decode(OWeather.self, from: data)\n                return result\n            } catch {\n                // Handle error\n                assertionFailure(\"Error decoding Weather: \\(error.localizedDescription)\")\n                return nil\n            }\n        }\n        set {\n            do {\n                guard let newValue else { /* Don't store nil */ return }\n                let data = try JSONEncoder().encode(newValue)\n                try FileManager.default.createDirectory(atPath: Cache.supportPath, withIntermediateDirectories: true)\n                try data.write(to: Self.cachedWeatherURL)\n            } catch {\n                // Handle error\n                assertionFailure(\"Error encoding Weather: \\(error.localizedDescription)\")\n            }\n        }\n    }\n\n    var cachedForecast: ForecastElement? {\n        get {\n            let fm = FileManager.default\n            guard fm.fileExists(atPath: WeatherLayer.cachedWeatherForecastURL.path) else { return nil }\n            do {\n                guard let date = try fm.attributesOfItem(atPath: WeatherLayer.cachedWeatherForecastURL.path)[.modificationDate] as? Date else {\n                 assertionFailure(\"Couldn't get modificationDate from File System!\")\n                 return nil\n                }\n                // Make sure the cache was written in the last \"update interval\" seconds, otherwise download now\n                guard date >= Date().addingTimeInterval(-WeatherLayer.cachedWeatherUpdateInterval) else { return nil }\n                let data = try Data(contentsOf: WeatherLayer.cachedWeatherForecastURL)\n                let result = try JSONDecoder().decode(ForecastElement.self, from: data)\n                return result\n            } catch {\n                // Handle error\n                assertionFailure(\"Error decoding Weather: \\(error.localizedDescription)\")\n                return nil\n            }\n        }\n        set {\n            do {\n                guard let newValue else { /* Don't store nil */ return }\n                let data = try JSONEncoder().encode(newValue)\n                try FileManager.default.createDirectory(atPath: Cache.supportPath, withIntermediateDirectories: true)\n                try data.write(to: Self.cachedWeatherForecastURL)\n            } catch {\n                // Handle error\n                assertionFailure(\"Error encoding Weather: \\(error.localizedDescription)\")\n            }\n        }\n    }\n\n    override init(layer: Any) {\n        super.init(layer: layer)\n    }\n\n    required init?(coder: NSCoder) {\n        fatalError(\"init(coder:) has not been implemented\")\n    }\n\n    // Our inits\n    override init(withLayer: CALayer, isPreview: Bool, offsets: LayerOffsets, manager: LayerManager) {\n        super.init(withLayer: withLayer, isPreview: isPreview, offsets: offsets, manager: manager)\n\n        // Always on layers should start with full opacity\n        self.opacity = 1\n    }\n\n    convenience init(withLayer: CALayer, isPreview: Bool, offsets: LayerOffsets, manager: LayerManager, config: PrefsInfo.Weather) {\n        self.init(withLayer: withLayer, isPreview: isPreview, offsets: offsets, manager: manager)\n        self.config = config\n\n/*        // Set our layer's font & corner now\n        (self.font, self.fontSize) = getFont(name: config.fontName,\n                                             size: config.fontSize)*/\n        self.corner = config.corner\n    }\n\n    override func setContentScale(scale: CGFloat) {\n        if let todayCond = todayCond {\n            todayCond.contentsScale = scale\n\n            if todayCond.sublayers != nil {\n                for layer in todayCond.sublayers! {\n                    layer.contentsScale = scale\n                }\n            }\n        }\n\n        if let forecastCond = forecastCond {\n            forecastCond.contentsScale = scale\n        }\n        // In case we haven't called displayWeatherBlock yet (should be all the time but hmm)\n        cscale = scale\n    }\n\n    // Called at each new video, we only setup once though !\n    override func setupForVideo(video: AerialVideo, player: AVPlayer) {\n        // Only run this once\n        if !wasSetup {\n            wasSetup = true\n            frame.size = CGSize(width: 100, height: 1)\n            update()\n        }\n        \n        if PrefsInfo.weather.mode == .current {\n            if cachedWeather != nil {\n                debugLog(\"weather using cache\")\n                displayWeatherBlock()\n            } else {\n                debugLog(\"fetching fresh weather\")\n                OpenWeather.fetch { result in\n                    switch result {\n                    case .success(let openWeather):\n                        self.cachedWeather = openWeather\n                        self.displayWeatherBlock()\n                    case .failure(let error):\n                        debugLog(error.localizedDescription)\n                    }\n                }\n            }\n        } else {\n            if cachedForecast != nil && cachedWeather != nil {\n                debugLog(\"weather using cache\")\n                displayWeatherBlock()\n            } else {\n                debugLog(\"fetching fresh weather\")\n                Forecast.fetch { result in\n                    switch result {\n                    case .success(let openWeather):\n                        self.cachedForecast = openWeather\n                        // self.displayWeatherBlock()\n                        OpenWeather.fetch { result in\n                            switch result {\n                            case .success(let openWeather):\n                                self.cachedWeather = openWeather\n                                self.displayWeatherBlock()\n                            case .failure(let error):\n                                debugLog(error.localizedDescription)\n                            }\n                        }\n                    case .failure(let error):\n                        debugLog(error.localizedDescription)\n                    }\n                }\n            }\n        }\n    }\n\n    func displayWeatherBlock() {\n        guard cachedWeather != nil || cachedForecast != nil else {\n            errorLog(\"No weather info in dWB please report\")\n            return\n        }\n        \n        todayCond?.removeFromSuperlayer()\n        todayCond = nil\n        forecastCond?.removeFromSuperlayer()\n        forecastCond = nil\n\n        if PrefsInfo.weather.mode == .current {\n            todayCond = ConditionLayer(condition: cachedWeather!, scale: contentsScale)\n            if cscale != nil {\n                todayCond!.contentsScale = cscale!\n            }\n            todayCond!.anchorPoint = CGPoint(x: 0, y: 0)\n            todayCond!.position = CGPoint(x: 0, y: 10)\n            addSublayer(todayCond!)\n\n            self.frame.size = todayCond!.frame.size\n        } else {\n            todayCond = ConditionLayer(condition: cachedWeather!, scale: contentsScale)\n            if cscale != nil {\n                todayCond!.contentsScale = cscale!\n            }\n            todayCond!.anchorPoint = CGPoint(x: 0, y: 0)\n            addSublayer(todayCond!)\n\n            forecastCond = ForecastLayer(condition: cachedForecast!, scale: contentsScale)\n            if cscale != nil {\n                forecastCond!.contentsScale = cscale!\n            }\n            forecastCond!.anchorPoint = CGPoint(x: 0, y: 0)\n            forecastCond!.position = CGPoint(x: todayCond!.frame.width, y: 10)\n            addSublayer(forecastCond!)\n\n            todayCond!.position = CGPoint(x: 0, y: forecastCond!.frame.height\n                                                    - todayCond!.frame.height\n                                                    + 10)\n\n            self.frame.size = CGSize(width: todayCond!.frame.width + forecastCond!.frame.width, height: forecastCond!.frame.height)\n            // self.frame.size = forecastCond!.frame.size\n        }\n\n        update(redraw: true)\n        let fadeAnimation = self.createFadeInAnimation()\n        add(fadeAnimation, forKey: \"weatherfade\")\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Views/Layers/Weather/WindDirectionLayer.swift",
    "content": "//\n//  WindDirectionLayer.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 05/03/2021.\n//  Copyright © 2021 Guillaume Louel. All rights reserved.\n//\n\nimport Foundation\nimport AVKit\n\nclass WindDirectionLayer: CALayer {\n    init(direction: CGFloat, size: CGFloat) {\n        super.init()\n        let imagePath = Bundle(for: PanelWindowController.self).path(\n            forResource: \"location.north\",\n            ofType: \"pdf\")\n\n        let img = NSImage(contentsOfFile: imagePath!)\n        frame.size.height = size\n        frame.size.width = size\n        contents = img\n    }\n\n    required init?(coder: NSCoder) {\n        fatalError(\"init(coder:) has not been implemented\")\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Views/Layers/Weather/YahooLogoLayer.swift",
    "content": "//\n//  YahooLogoLayer.swift\n//  Aerial\n//      CALayer for Yahoo logo (attribution is required for API access)\n//\n//  Created by Guillaume Louel on 17/04/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Foundation\nimport AVKit\n\nclass YahooLayer: CALayer {\n    override init() {\n        super.init()\n        let imagePath = Bundle(for: PanelWindowController.self).path(\n            forResource: \"white_retina\",\n            ofType: \"png\")\n\n        let img = NSImage(contentsOfFile: imagePath!)\n        frame.size.height = img!.size.height / 3\n        frame.size.width = img!.size.width / 3\n        contents = img\n    }\n\n    required init?(coder: NSCoder) {\n        fatalError(\"init(coder:) has not been implemented\")\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Views/MainUI/AspectFillNSImageView.swift",
    "content": "//\n//  AspectFillNSImageView.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 20/07/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Cocoa\n\nopen class AspectFillNSImageView: NSImageView {\n\n    open override var image: NSImage? {\n        get {\n            return super.image\n        }\n\n        set {\n            self.layer = CALayer()\n            if #available(macOS 10.14, *) {\n                self.layer?.contentsGravity = CALayerContentsGravity.resizeAspectFill\n            } else {\n                // Fallback on earlier versions\n            }\n            self.layer?.contents = newValue\n            self.wantsLayer = true\n\n            super.image = newValue\n        }\n    }\n\n    public override init(frame frameRect: NSRect) {\n        super.init(frame: frameRect)\n    }\n\n    // the image setter isn't called when loading from a storyboard\n    // manually set the image if it is already set\n    required public init?(coder: NSCoder) {\n        super.init(coder: coder)\n\n        if let theImage = image {\n            self.image = theImage\n        }\n    }\n\n}\n"
  },
  {
    "path": "Aerial/Source/Views/MainUI/NowPlayingCollectionView.swift",
    "content": "//\n//  NowPlayingCollectionView.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 18/08/2022.\n//  Copyright © 2022 Guillaume Louel. All rights reserved.\n//\n\nimport Cocoa\n\nclass NowPlayingCollectionView: NSCollectionView {\n\n    var clickedIndex: Int?\n\n    override func menu(for event: NSEvent) -> NSMenu? {\n        clickedIndex = nil\n\n        let point = convert(event.locationInWindow, from: nil)\n        for index in 0..<numberOfItems(inSection: 0) {\n            let frame = frameForItem(at: index)\n            if NSMouseInRect(point, frame, isFlipped) {\n                clickedIndex = index\n                break\n            }\n        }\n\n        return super.menu(for: event)\n    }\n    \n}\n"
  },
  {
    "path": "Aerial/Source/Views/MainUI/ShadowTextFieldCell.swift",
    "content": "//\n//  ShadowTextFieldCell.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 16/07/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Cocoa\n\nclass ShadowTextFieldCell: NSTextFieldCell {\n\n}\n"
  },
  {
    "path": "Aerial/Source/Views/MainUI/SidebarOutlineView.swift",
    "content": "//\n//  SidebarOutlineView.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 02/08/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Cocoa\n\nprotocol SidebarOutlineViewDelegate: NSOutlineViewDelegate {\n    func outlineView(outlineView: NSOutlineView, menuForItem item: Any) -> NSMenu?\n}\n\nclass SidebarOutlineView: NSOutlineView {\n\n    /*override func menu(for event: NSEvent) -> NSMenu? {\n        let point = self.convert(event.locationInWindow, from: nil)\n        let row = self.row(at: point)\n\n        if let item = self.item(atRow: row) {\n            return (self.delegate as! SidebarOutlineViewDelegate).outlineView(outlineView: self, menuForItem: item)\n\n        }\n\n        return nil\n    }*/\n\n}\n"
  },
  {
    "path": "Aerial/Source/Views/MainUI/VideoCellView.swift",
    "content": "//\n//  VideoCellView.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 16/07/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Cocoa\n\nclass VideoCellView: NSTableCellView {\n\n    @IBOutlet var thumbView: NSImageView!\n    @IBOutlet var label: NSTextField!\n    @IBOutlet var checkButton: NSButton!\n    @IBOutlet var downloadButton: NSButton!\n\n    // var delegate: VideoCellViewDelegate?\n    var video: AerialVideo?\n\n    override func draw(_ dirtyRect: NSRect) {\n        super.draw(dirtyRect)\n\n        checkButton.target = self\n        checkButton.action = #selector(self.didChangeState(_:))\n        checkButton.image = Aerial.helper.getSymbol(\"star\")!.tinting(with: .white)\n        checkButton.alternateImage = Aerial.helper.getSymbol(\"star.fill\")!.tinting(with: .white)\n\n        let shadow: NSShadow = NSShadow()\n        shadow.shadowBlurRadius = 2\n        shadow.shadowOffset = NSSize(width: 0, height: 2)\n        shadow.shadowColor = NSColor.black\n\n        checkButton.shadow = shadow\n        downloadButton.shadow = shadow\n\n        // Drawing code here.\n    }\n\n    // Notify the delegate that the checkbox's state has changed\n    @objc private func didChangeState(_ sender: NSObject) {\n        if PrefsVideos.favorites.contains(video!.id) {\n            PrefsVideos.favorites.remove(at: PrefsVideos.favorites.firstIndex(of: video!.id)!)\n        } else {\n            if !video!.isAvailableOffline {\n                Cache.ensureDownload {\n                    PrefsVideos.favorites.append(self.video!.id)\n                    VideoManager.sharedInstance.queueDownload(self.video!)\n                }\n            } else {\n                PrefsVideos.favorites.append(self.video!.id)\n            }\n        }\n    }\n\n    @IBAction func downloadButtonClick(_ sender: NSButton) {\n        let videoManager = VideoManager.sharedInstance\n        Cache.ensureDownload {\n            videoManager.queueDownload(self.video!)\n        }\n    }\n\n}\n"
  },
  {
    "path": "Aerial/Source/Views/PrefPanel/CheckCellView.swift",
    "content": "//\n//  CheckCellView.swift\n//  Aerial\n//\n//  Created by John Coates on 10/24/15.\n//  Copyright © 2015 John Coates. All rights reserved.\n//\n\nimport Cocoa\n\nenum VideoStatus {\n    case unknown, notAvailable, queued, downloading, downloaded\n}\n\nfinal class CheckCellView: NSTableCellView {\n\n    @IBOutlet var checkButton: NSButton!\n    @IBOutlet var addButton: NSButton!\n    @IBOutlet var progressIndicator: NSProgressIndicator!\n    @IBOutlet var formatLabel: NSTextField!\n    @IBOutlet var queuedImage: NSImageView!\n    @IBOutlet var mainTextField: NSTextField!\n\n    var onCheck: ((Bool) -> Void)?\n    var video: (AerialVideo)?\n    var status = VideoStatus.unknown\n\n    override required init(frame frameRect: NSRect) {\n        super.init(frame: frameRect)\n    }\n\n    required init?(coder: NSCoder) {\n        super.init(coder: coder)\n    }\n\n    override func awakeFromNib() {\n        checkButton.target = self\n        checkButton.action = #selector(CheckCellView.check(_:))\n    }\n\n    @objc func check(_ button: AnyObject?) {\n        guard let onCheck = self.onCheck else {\n            return\n        }\n\n        onCheck(checkButton.state == NSControl.StateValue.on)\n    }\n\n    override func draw(_ dirtyRect: NSRect) {\n        super.draw(dirtyRect)\n    }\n\n    func adaptIndicators() {\n        let videoManager = VideoManager.sharedInstance\n\n        if #available(OSX 10.12.2, *) {\n            queuedImage.image = NSImage(named: NSImage.touchBarDownloadTemplateName)\n        }\n        if video!.isAvailableOffline {\n            status = .downloaded\n            addButton.isHidden = true\n            progressIndicator.isHidden = true\n            queuedImage.isHidden = true\n        } else if videoManager.isVideoQueued(id: video!.id) {\n            status = .queued\n            addButton.isHidden = true\n            progressIndicator.isHidden = true\n            queuedImage.isHidden = false\n        } else {\n            status = .notAvailable\n            addButton.isHidden = false\n            progressIndicator.isHidden = true\n            queuedImage.isHidden = true\n        }\n\n        // formatLabel.isHidden = !(video!.has4KVersion())\n    }\n\n    func updateProgressIndicator(progress: Double) {\n        if status != .downloading {\n            addButton.isHidden = true\n            progressIndicator.isHidden = false\n            queuedImage.isHidden = true\n            status = .downloading\n        }\n        progressIndicator.doubleValue = Double(progress)\n    }\n\n    // Add video handling\n    func setVideo(video: AerialVideo) {\n        self.video = video\n    }\n\n    func markAsDownloaded() {\n        addButton.isHidden = true\n        progressIndicator.isHidden = true\n        queuedImage.isHidden = true\n        status = .downloaded\n\n        debugLog(\"Video download finished\")\n        video!.updateDuration()\n    }\n\n    func markAsNotDownloaded() {\n        addButton.isHidden = false\n        progressIndicator.isHidden = true\n        queuedImage.isHidden = true\n        status = .notAvailable\n\n        debugLog(\"Video download finished with error/cancel\")\n    }\n\n    func markAsQueued() {\n        debugLog(\"Queued \\(video!)\")\n        status = .queued\n        addButton.isHidden = true\n        progressIndicator.isHidden = true\n        queuedImage.isHidden = false\n    }\n\n    func queueVideo() {\n        let videoManager = VideoManager.sharedInstance\n        Cache.ensureDownload {\n            videoManager.queueDownload(self.video!)\n        }\n    }\n\n    @IBAction func addClick(_ button: NSButton?) {\n        queueVideo()\n    }\n}\n\nfinal class VerticallyAlignedTextFieldCell: NSTextFieldCell {\n    override func drawingRect(forBounds rect: NSRect) -> NSRect {\n        let newRect = NSRect(x: 0, y: (rect.size.height - 20) / 2, width: rect.size.width, height: 20)\n        return super.drawingRect(forBounds: newRect)\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Views/PrefPanel/DisplayView.swift",
    "content": "//\n//  DisplayView.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 09/05/2019.\n//  Copyright © 2019 John Coates. All rights reserved.\n//\n\nimport Foundation\nimport Cocoa\n\nclass DisplayPreview: NSObject {\n    var screen: Screen\n    var previewRect: CGRect\n\n    init(screen: Screen, previewRect: CGRect) {\n        self.screen = screen\n        self.previewRect = previewRect\n    }\n}\n\nextension NSImage {\n    func flipped(flipHorizontally: Bool = false, flipVertically: Bool = false) -> NSImage {\n        let flippedImage = NSImage(size: size)\n\n        flippedImage.lockFocus()\n\n        NSGraphicsContext.current?.imageInterpolation = .high\n\n        let transform = NSAffineTransform()\n        transform.translateX(by: flipHorizontally ? size.width : 0, yBy: flipVertically ? size.height : 0)\n        transform.scaleX(by: flipHorizontally ? -1 : 1, yBy: flipVertically ? -1 : 1)\n        transform.concat()\n\n        draw(at: .zero, from: NSRect(origin: .zero, size: size), operation: .sourceOver, fraction: 1)\n\n        flippedImage.unlockFocus()\n\n        return flippedImage\n    }\n}\n\nclass DisplayView: NSView {\n    // We store our computed previews here\n    var displayPreviews = [DisplayPreview]()\n\n    // MARK: - Lifecycle\n    override init(frame: CGRect) {\n        super.init(frame: frame)\n    }\n\n    required init?(coder: NSCoder) {\n        super.init(coder: coder)\n    }\n\n    // MARK: - Drawing\n    // swiftlint:disable:next cyclomatic_complexity\n    override func draw(_ dirtyRect: NSRect) {\n        super.draw(dirtyRect)\n\n        // We need to handle dark mode\n        var backgroundColor = NSColor.init(white: 0.9, alpha: 1.0)\n        var borderColor = NSColor.init(white: 0.8, alpha: 1.0)\n\n        // let screenColor = NSColor.init(red: 0.38, green: 0.60, blue: 0.85, alpha: 1.0)\n        let screenBorderColor = NSColor.black\n\n        if DarkMode.isEnabled() {\n            backgroundColor = NSColor.init(white: 0.2, alpha: 1.0)\n            borderColor = NSColor.init(white: 0.6, alpha: 1.0)\n        }\n\n        // Draw background with a 1pt border\n        borderColor.setFill()\n        __NSRectFill(dirtyRect)\n\n        let path = NSBezierPath(rect: dirtyRect.insetBy(dx: 1, dy: 1))\n        backgroundColor.setFill()\n        path.fill()\n\n        let displayDetection = DisplayDetection.sharedInstance\n        displayPreviews = [DisplayPreview]()    // Empty the array in case we redraw\n\n        // In order to draw the screen we need to know the total size of all\n        // the displays together\n        let globalRect = displayDetection.getGlobalScreenRect()\n\n        var minX: CGFloat, minY: CGFloat, maxX: CGFloat, maxY: CGFloat, scaleFactor: CGFloat\n        if (frame.width / frame.height) > (globalRect.width / globalRect.height) {\n            // We fill vertically then\n            maxY = frame.height - 60\n            minY = 30\n            scaleFactor = globalRect.height / maxY\n            maxX = globalRect.width / scaleFactor\n            minX = (frame.width - maxX)/2\n        } else {\n            // We fill horizontally\n            maxX = frame.width - 60\n            minX = 30\n            scaleFactor = globalRect.width / maxX\n            maxY = globalRect.height / scaleFactor\n            minY = (frame.height - maxY)/2\n        }\n\n        // In spanned mode, we start by a faint full view of the span\n        if PrefsDisplays.viewingMode == .spanned {\n            let activeRect = displayDetection.getZeroedActiveSpannedRect()\n            debugLog(\"spanned active rect \\(activeRect)\")\n            let activeSRect = NSRect(x: minX + (activeRect.origin.x/scaleFactor),\n                               y: minY + (activeRect.origin.y/scaleFactor),\n                               width: activeRect.width/scaleFactor,\n                               height: activeRect.height/scaleFactor)\n\n            let bundle = Bundle(for: PanelWindowController.self)\n            if let imagePath = bundle.path(forResource: \"screen0\", ofType: \"jpg\") {\n                let image = NSImage(contentsOfFile: imagePath)\n                image!.draw(in: activeSRect, from: calcScreenshotRect(src: activeSRect), operation: NSCompositingOperation.copy, fraction: 0.1)\n            } else {\n                errorLog(\"\\(#file) screenshot is missing!!!\")\n            }\n        }\n\n        var idx = 0\n        var shouldFlip = true\n        // Now we draw each individual screen\n        for screen in displayDetection.screens {\n            let sRect = NSRect(x: minX + (screen.zeroedOrigin.x/scaleFactor),\n                               y: minY + (screen.zeroedOrigin.y/scaleFactor),\n                               width: screen.bottomLeftFrame.width/scaleFactor,\n                               height: screen.bottomLeftFrame.height/scaleFactor)\n\n            let sPath = NSBezierPath(rect: sRect)\n            screenBorderColor.setFill()\n            sPath.fill()\n\n            let sInRect = sRect.insetBy(dx: 1, dy: 1)\n\n            if PrefsDisplays.viewingMode != .spanned {\n                if displayDetection.isScreenActive(id: screen.id) {\n                    let bundle = Bundle(for: PanelWindowController.self)\n                    if let imagePath = bundle.path(forResource: \"screen\"+String(idx), ofType: \"jpg\") {\n                        var image = NSImage(contentsOfFile: imagePath)\n\n                        if PrefsDisplays.viewingMode == .mirrored && shouldFlip {\n                            image = image?.flipped(flipHorizontally: true, flipVertically: false)\n                        }\n\n                        shouldFlip = !shouldFlip\n\n                        image!.draw(in: sInRect, from: calcScreenshotRect(src: sInRect), operation: NSCompositingOperation.copy, fraction: 1.0)\n                    } else {\n                        errorLog(\"\\(#file) screenshot is missing!!!\")\n                    }\n\n                    // Show difference images in independant mode to simulate\n                    if PrefsDisplays.viewingMode == .independent {\n                        if idx < 2 {\n                            idx += 1\n                        } else {\n                            idx = 0\n                        }\n                    }\n                } else {\n                    // If the screen is innactive we fill it with a near black color\n                    let sInPath = NSBezierPath(rect: sInRect)\n                    let grey = NSColor(white: 0.1, alpha: 1.0)\n                    grey.setFill()\n                    sInPath.fill()\n                }\n            } else {\n                // Spanned mode\n                if displayDetection.isScreenActive(id: screen.id) {\n                    // Calculate which portion of the image to display\n                    let activeRect = displayDetection.getZeroedActiveSpannedRect()\n                    let activeSRect = NSRect(x: minX + (activeRect.origin.x/scaleFactor),\n                                             y: minY + (activeRect.origin.y/scaleFactor),\n                                             width: activeRect.width/scaleFactor,\n                                             height: activeRect.height/scaleFactor)\n                    let ssRect = calcScreenshotRect(src: activeSRect)\n                    let xFactor = ssRect.width / activeSRect.width\n                    let yFactor = ssRect.height / activeSRect.height\n                    // ...\n                    let sFRect = CGRect(x: (sInRect.origin.x - activeSRect.origin.x) * xFactor + ssRect.origin.x,\n                                        y: (sInRect.origin.y - activeSRect.origin.y) * yFactor + ssRect.origin.y,\n                                        width: sInRect.width*xFactor,\n                                        height: sInRect.height*yFactor)\n\n                    let bundle = Bundle(for: PanelWindowController.self)\n                    if let imagePath = bundle.path(forResource: \"screen0\", ofType: \"jpg\") {\n                        let image = NSImage(contentsOfFile: imagePath)\n                        // image!.draw(in: sInRect)\n                        image!.draw(in: sInRect, from: sFRect, operation: NSCompositingOperation.copy, fraction: 1.0)\n                    } else {\n                        errorLog(\"\\(#file) screenshot is missing!!!\")\n                    }\n                }\n            }\n\n            // We preserve those calculations to handle our clicking logic\n            displayPreviews.append(DisplayPreview(screen: screen, previewRect: sInRect))\n\n            // We put a white bar on the main screen\n            if screen.isMain {\n                let mainRect = CGRect(x: sRect.origin.x, y: sRect.origin.y + sRect.height-8, width: sRect.width, height: 8)\n                let sMainPath = NSBezierPath(rect: mainRect)\n                NSColor.black.setFill()\n                sMainPath.fill()\n                let sMainInPath = NSBezierPath(rect: mainRect.insetBy(dx: 1, dy: 1))\n                NSColor.white.setFill()\n                sMainInPath.fill()\n            }\n        }\n    }\n\n    // Helper to keep aspect ratio of screenshots to be displayed\n    func calcScreenshotRect(src: CGRect) -> CGRect {\n        var minX: CGFloat, minY: CGFloat, maxX: CGFloat, maxY: CGFloat, scaleFactor: CGFloat\n\n        let imgw: CGFloat = 720\n        let imgh: CGFloat = 400\n\n        if (imgw/imgh) < (src.width/src.height) {\n            minX = 0\n            maxX = imgw\n            scaleFactor = src.width / maxX\n            maxY = src.height / scaleFactor\n            minY = (imgh - maxY)/2\n        } else {\n            minY = 0\n            maxY = imgh\n            scaleFactor = src.height / maxY\n            maxX = src.width / scaleFactor\n            minX = (imgw - maxX)/2\n        }\n\n        return CGRect(x: minX, y: minY, width: maxX, height: maxY)\n    }\n\n    // MARK: - Clicking\n    override func mouseDown(with event: NSEvent) {\n        let displayDetection = DisplayDetection.sharedInstance\n\n        // Grab relative location of the click in view\n        let point = convert(event.locationInWindow, from: nil)\n\n        // If in selection mode, toggle the screen & redraw\n        if PrefsDisplays.displayMode == .selection {\n            for displayPreview in displayPreviews {\n                if displayPreview.previewRect.contains(point) {\n                    if displayDetection.isScreenActive(id: displayPreview.screen.id) {\n                        displayDetection.unselectScreen(id: displayPreview.screen.id)\n                    } else {\n                        displayDetection.selectScreen(id: displayPreview.screen.id)\n                    }\n                    debugLog(\"Clicked on \\(displayPreview.screen.id)\")\n                    self.needsDisplay = true\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Views/PrefPanel/InfoBatteryView.swift",
    "content": "//\n//  InfoBatteryView.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 27/12/2019.\n//  Copyright © 2019 Guillaume Louel. All rights reserved.\n//\n\nimport Cocoa\n\nclass InfoBatteryView: NSView {\n    @IBOutlet var hideWhenFull: NSButton!\n\n    // Init(ish)\n    func setStates() {\n        hideWhenFull.state = PrefsInfo.battery.disableWhenFull ? .on : .off\n    }\n\n    @IBAction func hideWhenFullCheck(_ sender: NSButton) {\n        let onState = sender.state == .on\n        PrefsInfo.battery.disableWhenFull = onState\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Views/PrefPanel/InfoClockView.swift",
    "content": "//\n//  InfoClockView.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 18/12/2019.\n//  Copyright © 2019 Guillaume Louel. All rights reserved.\n//\n\nimport Cocoa\n\nclass InfoClockView: NSView {\n    @IBOutlet var secondsCheckbox: NSButton!\n    @IBOutlet var hideAmPmCheckbox: NSButton!\n    @IBOutlet var clockFormat: NSPopUpButton!\n\n    @IBOutlet var customTimeFormatField: NSTextField!\n\n    // Init(ish)\n    func setStates() {\n        secondsCheckbox.state = PrefsInfo.clock.showSeconds ? .on : .off\n        hideAmPmCheckbox.state = PrefsInfo.clock.hideAmPm ? .on : .off\n        clockFormat.selectItem(at: PrefsInfo.clock.clockFormat.rawValue)\n\n        customTimeFormatField.stringValue = PrefsInfo.customTimeFormat\n        updateAmPmCheckbox()\n    }\n\n    @IBAction func secondsClick(_ sender: NSButton) {\n        let onState = sender.state == .on\n        PrefsInfo.clock.showSeconds = onState\n    }\n\n    @IBAction func hideAmPmCheckboxClick(_ sender: NSButton) {\n        let onState = sender.state == .on\n        PrefsInfo.clock.hideAmPm = onState\n    }\n\n    @IBAction func clockFormatChange(_ sender: NSPopUpButton) {\n        PrefsInfo.clock.clockFormat = InfoClockFormat(rawValue: sender.indexOfSelectedItem)!\n        updateAmPmCheckbox()\n    }\n\n    // Update the 12/24hr visibility\n    func updateAmPmCheckbox() {\n        switch PrefsInfo.clock.clockFormat {\n        case .tdefault:\n            hideAmPmCheckbox.isHidden = false  // meh\n            secondsCheckbox.isHidden = false\n        case .t12hours:\n            hideAmPmCheckbox.isHidden = false\n            secondsCheckbox.isHidden = false\n        case .t24hours:\n            hideAmPmCheckbox.isHidden = true\n            secondsCheckbox.isHidden = false\n        case .custom:\n            hideAmPmCheckbox.isHidden = true\n            secondsCheckbox.isHidden = true\n        }\n\n        customTimeFormatField.isHidden = !(PrefsInfo.clock.clockFormat == .custom)\n    }\n\n    @IBAction func customTimeFormatFieldChange(_ sender: NSTextField) {\n        PrefsInfo.customTimeFormat = sender.stringValue\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Views/PrefPanel/InfoCommonView.swift",
    "content": "//\n//  InfoCommonView.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 17/12/2019.\n//  Copyright © 2019 Guillaume Louel. All rights reserved.\n//\n\nimport Cocoa\n\nclass InfoCommonView: NSView {\n    var forType: InfoType = .location\n    var controller: OverlaysViewController?\n\n    @IBOutlet var enabledButton: NSButton!\n    @IBOutlet var fontLabel: NSTextField!\n\n    @IBOutlet var displaysPopup: NSPopUpButton!\n\n    @IBOutlet var posTopLeft: NSButton!\n    @IBOutlet var posTopCenter: NSButton!\n    @IBOutlet var posTopRight: NSButton!\n    @IBOutlet var posBottomLeft: NSButton!\n    @IBOutlet var posBottomCenter: NSButton!\n    @IBOutlet var posBottomRight: NSButton!\n    @IBOutlet var posScreenCenter: NSButton!\n    @IBOutlet var posRandom: NSButton!\n\n    // MARK: - init(ish)\n    // This is what tells us what we are editing exactly\n    func setType(_ forType: InfoType, controller: OverlaysViewController) {\n        // We need the controller for callbacks, when we update the isEnabled state,\n        // we need to update the list view on the left too\n        self.controller = controller\n        \n        // Store type\n        self.forType = forType\n\n        // Update our states\n        enabledButton.state = PrefsInfo.ofType(forType).isEnabled ? .on : .off\n        setPosition(PrefsInfo.ofType(forType).corner)\n        displaysPopup.selectItem(at: PrefsInfo.ofType(forType).displays.rawValue)\n        fontLabel.stringValue = PrefsInfo.ofType(forType).fontName + \", \\(PrefsInfo.ofType(forType).fontSize) pt\"\n\n        switch forType {\n        case .location:\n            //controller.infoBox.title = \"Video location information\"\n            posRandom.isHidden = false\n        case .message:\n            //controller.infoBox.title = \"Custom message\"\n            posRandom.isHidden = true\n        case .clock:\n            //controller.infoBox.title = \"Current time\"\n            posRandom.isHidden = true\n        case .date:\n            //controller.infoBox.title = \"Current date\"\n            posRandom.isHidden = true\n        case .battery:\n            //controller.infoBox.title = \"Battery status\"\n            posRandom.isHidden = true\n        case .updates:\n            //controller.infoBox.title = \"Updates notifications\"\n            posRandom.isHidden = true\n        case .weather:\n            //controller.infoBox.title = \"Weather provided by OpenWeather\"\n            posRandom.isHidden = true\n        case .countdown:\n            //controller.infoBox.title = \"Countdown to a time/date\"\n            posRandom.isHidden = true\n        case .timer:\n            //controller.infoBox.title = \"Timer\"\n            posRandom.isHidden = true\n        case .music:\n            //controller.infoBox.title = \"Music\"\n            posRandom.isHidden = true\n        }\n    }\n\n    // MARK: - Position on screen\n\n    func setPosition(_ corner: InfoCorner) {\n        switch corner {\n        case .topLeft:\n            posTopLeft.state = .on\n        case .topCenter:\n            posTopCenter.state = .on\n        case .topRight:\n            posTopRight.state = .on\n        case .bottomLeft:\n            posBottomLeft.state = .on\n        case .bottomCenter:\n            posBottomCenter.state = .on\n        case .bottomRight:\n            posBottomRight.state = .on\n        case .screenCenter:\n            posScreenCenter.state = .on\n        case .random:\n            posRandom.state = .on\n        case .absTopRight:\n            posTopRight.state = .on\n        }\n    }\n\n    @IBAction func changePosition(_ sender: NSButton) {\n        var pos: InfoCorner\n\n        // Which button ?\n        switch sender {\n        case posTopLeft:\n            pos = .topLeft\n        case posTopCenter:\n            pos = .topCenter\n        case posTopRight:\n            pos = .topRight\n        case posBottomLeft:\n            pos = .bottomLeft\n        case posBottomCenter:\n            pos = .bottomCenter\n        case posBottomRight:\n            pos = .bottomRight\n        case posScreenCenter:\n            pos = .screenCenter\n        case posRandom:\n            pos = .random\n        default:\n            pos = .bottomLeft\n        }\n\n        // Then set pref\n        PrefsInfo.setCorner(forType, corner: pos)\n    }\n\n    // MARK: - Displays it should appear on\n\n    @IBAction func changeDisplays(_ sender: NSPopUpButton) {\n        PrefsInfo.setDisplayMode(forType, mode: InfoDisplays(rawValue: sender.indexOfSelectedItem)!)\n    }\n\n    // MARK: - enabled\n\n    @IBAction func enabledClick(_ sender: NSButton) {\n        PrefsInfo.setEnabled(forType, value: sender.state == .on)\n\n        // We need to update the side column!\n        controller!.infoTableView.reloadDataKeepingSelection()\n    }\n\n    // MARK: - Font picker\n\n    @IBAction func changeFontClick(_ sender: Any) {\n        // Make sure we get the callback\n        NSFontManager.shared.target = self\n\n        // Make a panel\n        if let fp = NSFontManager.shared.fontPanel(true) {\n            fp.setPanelFont(makeFont(name: PrefsInfo.ofType(forType).fontName,\n                                     size: PrefsInfo.ofType(forType).fontSize), isMultiple: false)\n\n            // Push the panel\n            fp.makeKeyAndOrderFront(sender)\n        }\n    }\n\n    func makeFont(name: String, size: Double) -> NSFont {\n        if let font = NSFont(name: name, size: CGFloat(size)) {\n            return font\n        } else {\n            // This is probably enough\n            return NSFont(name: \"Helvetica Neue Medium\", size: 28)!\n        }\n    }\n\n    @IBAction func resetFontClick(_ sender: Any) {\n        // We use a default font for all types\n        PrefsInfo.setFontName(forType, name: \"Helvetica Neue Medium\")\n\n        // Default Size varies though per type\n        switch forType {\n        case .location:\n            PrefsInfo.location.fontSize = 28\n        case .message:\n            PrefsInfo.message.fontSize = 20\n        case .clock:\n            PrefsInfo.clock.fontSize = 50\n        case .date:\n            PrefsInfo.date.fontSize = 20\n        case .battery:\n            PrefsInfo.battery.fontSize = 20\n        case .updates:\n            PrefsInfo.updates.fontSize = 20\n        case .weather:\n            PrefsInfo.weather.fontSize = 20\n        case .countdown:\n            PrefsInfo.countdown.fontSize = 100\n        case .timer:\n            PrefsInfo.timer.fontSize = 100\n        case .music:\n            PrefsInfo.music.fontSize = 20\n        }\n\n        fontLabel.stringValue = PrefsInfo.ofType(forType).fontName + \", \\(PrefsInfo.ofType(forType).fontSize) pt\"\n    }\n}\n\n// MARK: - Font Panel Delegates\n\nextension InfoCommonView: NSFontChanging {\n    func validModesForFontPanel(_ fontPanel: NSFontPanel) -> NSFontPanel.ModeMask {\n        return [.size, .collection, .face]\n    }\n\n    func changeFont(_ sender: NSFontManager?) {\n        // Set current font\n        let oldFont = makeFont(name: PrefsInfo.ofType(forType).fontName,\n                           size: PrefsInfo.ofType(forType).fontSize)\n\n        if let newFont = sender?.convert(oldFont) {\n            PrefsInfo.setFontName(forType, name: newFont.fontName)\n            PrefsInfo.setFontSize(forType, size: Double(newFont.pointSize))\n\n            fontLabel.stringValue = newFont.fontName + \", \\(Double(newFont.pointSize)) pt\"\n        } else {\n            errorLog(\"New font failure\")\n        }\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Views/PrefPanel/InfoContainerView.swift",
    "content": "//\n//  InfoContainerView.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 17/12/2019.\n//  Copyright © 2019 Guillaume Louel. All rights reserved.\n//\n\nimport Cocoa\n\nclass InfoContainerView: NSView {\n    // We need to override the coordinate mode (bottom left origin to top left origin)\n    // so we can later add our child views from top to bottom\n    override var isFlipped: Bool { return true }\n}\n"
  },
  {
    "path": "Aerial/Source/Views/PrefPanel/InfoCountdownView.swift",
    "content": "//\n//  InfoCountdownView.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 12/02/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Cocoa\n\nclass InfoCountdownView: NSView {\n\n    @IBOutlet var timeModePopup: NSPopUpButton!\n\n    @IBOutlet var withSecondsCheckbox: NSButton!\n    @IBOutlet var targetTimeDatePicker: NSDatePicker!\n    @IBOutlet var limitToIntervalCheckbox: NSButton!\n    @IBOutlet var limitIntervalDatePicker: NSDatePicker!\n\n    // Init(ish)\n    func setStates() {\n        timeModePopup.selectItem(at: PrefsInfo.countdown.mode.rawValue)\n        withSecondsCheckbox.state = PrefsInfo.countdown.showSeconds ? .on : .off\n\n        targetTimeDatePicker.dateValue = PrefsInfo.countdown.targetDate\n\n        updatePickerFormat()\n\n        limitToIntervalCheckbox.state = PrefsInfo.countdown.enforceInterval ? .on : .off\n        limitIntervalDatePicker.dateValue = PrefsInfo.countdown.triggerDate\n    }\n\n    func updatePickerFormat() {\n        switch PrefsInfo.countdown.mode {\n        case .preciseDate:\n            targetTimeDatePicker.datePickerElements = [.yearMonthDay, .hourMinuteSecond]\n            limitIntervalDatePicker.datePickerElements = [.yearMonthDay, .hourMinuteSecond]\n        case .timeOfDay:\n            targetTimeDatePicker.datePickerElements = [.hourMinuteSecond]\n            limitIntervalDatePicker.datePickerElements = [.hourMinuteSecond]\n            // TODO hide day\n        }\n    }\n\n    // UI Actions\n    @IBAction func timeModePopupChange(_ sender: NSPopUpButton) {\n        PrefsInfo.countdown.mode = InfoCountdownMode(rawValue: sender.indexOfSelectedItem)!\n        updatePickerFormat()\n    }\n\n    @IBAction func withSecondsCheckboxClick(_ sender: NSButton) {\n        let onState = sender.state == .on\n        PrefsInfo.countdown.showSeconds = onState\n    }\n\n    @IBAction func targetTimeDatePickerChange(_ sender: NSDatePicker) {\n        PrefsInfo.countdown.targetDate = sender.dateValue\n    }\n\n    @IBAction func limitToIntervalClick(_ sender: NSButton) {\n        let onState = sender.state == .on\n        PrefsInfo.countdown.enforceInterval = onState\n    }\n\n    @IBAction func limitIntervalDatePickerChange(_ sender: NSDatePicker) {\n        PrefsInfo.countdown.triggerDate = sender.dateValue\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Views/PrefPanel/InfoDateView.swift",
    "content": "//\n//  InfoDateView.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 23/03/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Cocoa\n\nclass InfoDateView: NSView {\n\n    @IBOutlet var dateFormatPopup: NSPopUpButton!\n\n    @IBOutlet var withYearCheckbox: NSButton!\n\n    @IBOutlet var customDateFormatField: NSTextField!\n\n    // Init(ish)\n    func setStates() {\n        dateFormatPopup.selectItem(at: PrefsInfo.date.format.rawValue)\n        withYearCheckbox.state = PrefsInfo.date.withYear ? .on : .off\n        withYearCheckbox.isHidden = (PrefsInfo.date.format == .custom)\n        customDateFormatField.stringValue = PrefsInfo.customDateFormat\n        customDateFormatField.isHidden = !(PrefsInfo.date.format == .custom)\n    }\n\n    @IBAction func dateFormatPopupChange(_ sender: NSPopUpButton) {\n        PrefsInfo.date.format = InfoDate(rawValue: sender.indexOfSelectedItem)!\n\n        withYearCheckbox.isHidden = (PrefsInfo.date.format == .custom)\n        customDateFormatField.isHidden = !(PrefsInfo.date.format == .custom)\n    }\n\n    @IBAction func withYearCheckboxChange(_ sender: NSButton) {\n        let onState = sender.state == .on\n        PrefsInfo.date.withYear = onState\n    }\n\n    @IBAction func customDateFormatFieldChange(_ sender: NSTextField) {\n        PrefsInfo.customDateFormat = sender.stringValue\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Views/PrefPanel/InfoLocationView.swift",
    "content": "//\n//  InfoLocationView.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 19/12/2019.\n//  Copyright © 2019 Guillaume Louel. All rights reserved.\n//\n\nimport Cocoa\n\nclass InfoLocationView: NSView {\n\n    @IBOutlet var showTimePopup: NSPopUpButton!\n\n    // Init(ish)\n    func setStates() {\n        showTimePopup.selectItem(at: PrefsInfo.location.time.rawValue)\n    }\n\n    @IBAction func showTimeChange(_ sender: NSPopUpButton) {\n        PrefsInfo.location.time = InfoTime(rawValue: sender.indexOfSelectedItem)!\n    }\n\n}\n"
  },
  {
    "path": "Aerial/Source/Views/PrefPanel/InfoMessageView.swift",
    "content": "//\n//  InfoMessageView.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 18/12/2019.\n//  Copyright © 2019 Guillaume Louel. All rights reserved.\n//\n\nimport Cocoa\n\nclass InfoMessageView: NSView, NSTextViewDelegate {\n    @IBOutlet var messageType: NSPopUpButton!\n\n    // Basic text view\n    @IBOutlet var messageTextView: NSTextView!\n\n    // Shell script view\n    @IBOutlet weak var shellScript: NSTextField!\n    @IBOutlet weak var shellScriptTest: NSButton!\n\n    @IBOutlet weak var shellRefreshPeriodicity: NSPopUpButton!\n    @IBOutlet weak var shellScriptLabel: NSTextField!\n\n    func setStates() {\n        messageType.selectItem(at: PrefsInfo.message.messageType.rawValue)\n\n        messageTextView.delegate = self\n        messageTextView.string = PrefsInfo.message.message\n\n        shellScript.stringValue = PrefsInfo.message.shellScript\n        shellRefreshPeriodicity.selectItem(at: PrefsInfo.message.refreshPeriodicity.rawValue)\n        shellScriptLabel.stringValue = \"\"\n    }\n\n    @IBAction func messageTypeChange(_ sender: NSPopUpButton) {\n        PrefsInfo.message.messageType = InfoMessageType(rawValue: sender.indexOfSelectedItem)!\n\n        guard let overlayController = self.parentViewController as? OverlaysViewController else {\n            return\n        }\n\n        overlayController.switchSubMessagePanel()\n    }\n\n    // Basic text\n    func textDidChange(_ notification: Notification) {\n        guard let textView = notification.object as? NSTextView else { return }\n        PrefsInfo.message.message = textView.string\n    }\n\n    // Shell script\n    @IBAction func shellScriptChange(_ sender: NSTextField) {\n        PrefsInfo.message.shellScript = sender.stringValue\n    }\n\n    @IBAction func shellScriptTestClick(_ sender: Any) {\n        PrefsInfo.message.shellScript = shellScript.stringValue\n\n        if PrefsInfo.message.shellScript != \"\" {\n            if FileManager.default.fileExists(atPath: PrefsInfo.message.shellScript) {\n                let (result, code) = Aerial.helper.shell(launchPath: PrefsInfo.message.shellScript)\n\n                if let res = result {\n                    shellScriptLabel.stringValue = res\n                } else {\n                    shellScriptLabel.stringValue = \"Empty return value, return code: \\(code)\"\n                }\n            } else {\n                shellScriptLabel.stringValue = \"No file found at your location, please check your path\"\n            }\n        } else {\n            shellScriptLabel.stringValue = \"Script location empty\"\n        }\n    }\n\n    @IBAction func shellRefreshPeriodicityChange(_ sender: NSPopUpButton) {\n        PrefsInfo.message.refreshPeriodicity = InfoRefreshPeriodicity(rawValue: sender.indexOfSelectedItem)!\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Views/PrefPanel/InfoMusicView.swift",
    "content": "//\n//  InfoMusicView.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 11/06/2021.\n//  Copyright © 2021 Guillaume Louel. All rights reserved.\n//\n\nimport Cocoa\n\nclass InfoMusicView: NSView {\n    // Init(ish)\n    func setStates() {\n        // Nothing here for now in new universal playback\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Views/PrefPanel/InfoSettingsTableSource.swift",
    "content": "//\n//  InfoSettingsTableSource.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 14/02/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Cocoa\n\nclass InfoSettingsTableSource: NSTableView, NSTableViewDataSource, NSTableViewDelegate {\n    var controller: OverlaysViewController?\n\n    func setController(_ controller: OverlaysViewController) {\n        self.controller = controller\n    }\n\n    override func draw(_ dirtyRect: NSRect) {\n        super.draw(dirtyRect)\n    }\n\n    func numberOfRows(in tableView: NSTableView) -> Int {\n        return 1\n    }\n\n    func tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat {\n        return 30\n    }\n\n    func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {\n        let cid = NSUserInterfaceItemIdentifier(rawValue: \"InfoSettingsCellID\")\n\n        if let cell = tableView.makeView(withIdentifier: cid, owner: self) as? NSTableCellView {\n            cell.textField?.stringValue = \"Text settings\"\n\n            if #available(OSX 10.12.2, *) {\n                cell.imageView?.image = NSImage(named: NSImage.touchBarTextBoxTemplateName)\n            } else {\n                // Fallback on earlier versions\n                cell.imageView?.image = NSImage(named: NSImage.fontPanelName)\n            }\n            return cell\n        }\n\n        return nil\n    }\n\n    // This is where selection happens\n    func tableViewSelectionDidChange(_ notification: Notification) {\n        let tableView = notification.object as! NSTableView\n        if tableView.selectedRow >= 0 {\n            controller!.drawInfoSettingsPanel()\n            controller!.infoTableView.deselectAll(controller!)\n        }\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Views/PrefPanel/InfoSettingsView.swift",
    "content": "//\n//  InfoSettingsView.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 14/02/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Cocoa\n\nclass InfoSettingsView: NSView {\n    @IBOutlet weak var fadeInOutTextModePopup: NSPopUpButton!\n\n    @IBOutlet var highQualityTextRendering: NSButton!\n    @IBOutlet var changeCornerMargins: NSButton!\n    @IBOutlet var marginHorizontalTextfield: NSTextField!\n    @IBOutlet var marginVerticalTextfield: NSTextField!\n\n    // Shadows\n    @IBOutlet var shadowRadiusTextField: NSTextField!\n    @IBOutlet var shadowRadiusFormatter: NumberFormatter!\n    @IBOutlet var shadowOpacitySlider: NSSlider!\n    @IBOutlet var shadowOffsetXTextfield: NSTextField!\n    @IBOutlet var shadowOffsetYTextfield: NSTextField!\n\n    @IBOutlet var shadowOffsetXFormatter: NumberFormatter!\n    @IBOutlet var shadowOffsetYFormatter: NumberFormatter!\n\n    func setStates() {\n        // Margins override\n        if PrefsInfo.overrideMargins {\n            changeCornerMargins.state = .on\n            marginHorizontalTextfield.isEnabled = true\n            marginVerticalTextfield.isEnabled = true\n        }\n\n        highQualityTextRendering.state = PrefsInfo.highQualityTextRendering ? .on : .off\n\n        marginHorizontalTextfield.stringValue = String(PrefsInfo.marginX)\n        marginVerticalTextfield.stringValue = String(PrefsInfo.marginY)\n\n        fadeInOutTextModePopup.selectItem(at: PrefsInfo.fadeModeText.rawValue)\n\n        shadowRadiusFormatter.allowsFloats = false\n        shadowRadiusTextField.stringValue = String(PrefsInfo.shadowRadius)\n\n        shadowOpacitySlider.doubleValue = Double(PrefsInfo.shadowOpacity * 100)\n        shadowOffsetXTextfield.doubleValue = Double(PrefsInfo.shadowOffsetX)\n        shadowOffsetYTextfield.doubleValue = Double(PrefsInfo.shadowOffsetY)\n    }\n\n    // MARK: - Shadows\n    @IBAction func highQualityTextRenderingChange(_ sender: NSButton) {\n        PrefsInfo.highQualityTextRendering = sender.state == .on\n    }\n\n    @IBAction func shadowRadiusChange(_ sender: NSTextField) {\n        PrefsInfo.shadowRadius = Int(sender.intValue)\n    }\n\n    @IBAction func shadowOpacityChange(_ sender: NSSlider) {\n        PrefsInfo.shadowOpacity = Float(sender.intValue)/100\n    }\n\n    @IBAction func shadowOffsetXChange(_ sender: NSTextField) {\n        PrefsInfo.shadowOffsetX = CGFloat(sender.doubleValue)\n    }\n\n    @IBAction func shadowOffsetYChange(_ sender: NSTextField) {\n        PrefsInfo.shadowOffsetY = CGFloat(sender.doubleValue)\n    }\n\n    // MARK: - Fades\n    @IBAction func fadeInOutTextModePopupChange(_ sender: NSPopUpButton) {\n        debugLog(\"UI fadeInOutTextMode: \\(sender.indexOfSelectedItem)\")\n\n        PrefsInfo.fadeModeText = FadeMode(rawValue: sender.indexOfSelectedItem)!\n\n    }\n\n    // MARK: - Margins\n    @IBAction func changeMarginsToCornerClick(_ sender: NSButton) {\n        let onState = sender.state == .on\n        debugLog(\"UI changeMarginsToCorner: \\(onState)\")\n\n        marginHorizontalTextfield.isEnabled = onState\n        marginVerticalTextfield.isEnabled = onState\n        PrefsInfo.overrideMargins = onState\n    }\n\n    @IBAction func marginXChange(_ sender: NSTextField) {\n        PrefsInfo.marginX = Int(sender.stringValue) ?? 50\n    }\n\n    @IBAction func marginYChange(_ sender: NSTextField) {\n        PrefsInfo.marginY = Int(sender.stringValue) ?? 50\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Views/PrefPanel/InfoTableSource.swift",
    "content": "//\n//  InfoTableSource.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 16/12/2019.\n//  Copyright © 2019 Guillaume Louel. All rights reserved.\n//\n\nimport Cocoa\n\nclass InfoTableSource: NSTableView, NSTableViewDataSource, NSTableViewDelegate {\n    private var dragDropType = NSPasteboard.PasteboardType(rawValue: \"private.table-row\")\n    var controller: OverlaysViewController?\n\n    func setController(_ controller: OverlaysViewController) {\n        self.controller = controller\n    }\n\n    override func draw(_ dirtyRect: NSRect) {\n        super.draw(dirtyRect)\n    }\n\n    func numberOfRows(in tableView: NSTableView) -> Int {\n        return PrefsInfo.layers.count\n    }\n\n    func tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat {\n        return 30\n    }\n\n    // This is where we fill each cell\n    func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {\n        if tableColumn == tableView.tableColumns[0] {\n            let cid = NSUserInterfaceItemIdentifier(rawValue: \"InfoSourceCellID\")\n\n            if let cell = tableView.makeView(withIdentifier: cid, owner: self) as? NSTableCellView {\n                cell.textField?.stringValue = PrefsInfo.layers[row].rawValue.capitalizeFirstLetter()\n\n                let isEnabled = PrefsInfo.ofType(PrefsInfo.layers[row]).isEnabled\n\n                // Aerial.getAccentedSymbol(<#T##named: String##String#>)\n                // Aerial.getSymbol(\"checkmark.circle.fill\")\n                cell.imageView?.image = isEnabled\n                ? Aerial.helper.getAccentedSymbol(\"checkmark.circle.fill\")\n                : Aerial.helper.getAccentedSymbol(\"circle\")\n                /*cell.imageView?.image = NSImage(named: isEnabled\n                    ? NSImage.statusAvailableName\n                    : NSImage.statusUnavailableName)*/\n\n                return cell\n            }\n        } else {\n            let cid = NSUserInterfaceItemIdentifier(rawValue: \"InfoSourceGripID\")\n\n            if let cell = tableView.makeView(withIdentifier: cid, owner: self) as? NSTableCellView {\n                cell.imageView?.image = NSImage(named: NSImage.listViewTemplateName)\n                return cell\n            }\n        }\n\n        return nil\n    }\n\n    // This is where selection happens\n    func tableViewSelectionDidChange(_ notification: Notification) {\n        let tableView = notification.object as! NSTableView\n        if tableView.selectedRow < 0 {\n            // controller!.resetInfoPanel()\n        } else {\n            controller!.drawInfoPanel(forType: PrefsInfo.layers[tableView.selectedRow])\n            controller!.infoSettingsTableView.deselectAll(controller!)\n\n        }\n    }\n\n    // MARK: - Drag 'n Drop\n    func tableView(_ tableView: NSTableView, pasteboardWriterForRow row: Int) -> NSPasteboardWriting? {\n        let item = NSPasteboardItem()\n        item.setString(String(row), forType: self.dragDropType)\n        return item\n    }\n\n    func tableView(_ tableView: NSTableView, validateDrop info: NSDraggingInfo, proposedRow row: Int, proposedDropOperation dropOperation: NSTableView.DropOperation) -> NSDragOperation {\n\n        if dropOperation == .above {\n            return .move\n        }\n        return []\n    }\n\n    func tableView(_ tableView: NSTableView, acceptDrop info: NSDraggingInfo, row: Int, dropOperation: NSTableView.DropOperation) -> Bool {\n\n        var oldIndexes = [Int]()\n        info.enumerateDraggingItems(options: [], for: tableView, classes: [NSPasteboardItem.self], searchOptions: [:]) { dragItem, _, _ in\n            if let str = (dragItem.item as! NSPasteboardItem).string(forType: self.dragDropType), let index = Int(str) {\n                oldIndexes.append(index)\n            }\n        }\n\n        var oldIndexOffset = 0\n        var newIndexOffset = 0\n\n        for oldIndex in oldIndexes {\n            if oldIndex < row {\n                PrefsInfo.layers.move(from: oldIndex + oldIndexOffset, to: row - 1)\n                oldIndexOffset -= 1\n            } else {\n                PrefsInfo.layers.move(from: oldIndex, to: row + newIndexOffset)\n                newIndexOffset += 1\n            }\n        }\n\n        tableView.reloadData()\n        return true\n    }\n}\n\n// Helpers to move items in array\nextension Array where Element: Equatable {\n    mutating func move(_ element: Element, to newIndex: Index) {\n        if let oldIndex: Int = self.firstIndex(of: element) { self.move(from: oldIndex, to: newIndex) }\n    }\n}\n\nextension Array {\n    mutating func move(from oldIndex: Index, to newIndex: Index) {\n        // Don't work for free and use swap when indices are next to each other - this\n        // won't rebuild array and will be super efficient.\n        if oldIndex == newIndex { return }\n        if abs(newIndex - oldIndex) == 1 { return self.swapAt(oldIndex, newIndex) }\n        self.insert(self.remove(at: oldIndex), at: newIndex)\n    }\n}\n\nextension String {\n     func capitalizeFirstLetter() -> String {\n          return self.prefix(1).capitalized + dropFirst()\n     }\n}\n\nextension NSTableView {\n    func reloadDataKeepingSelection() {\n        let selectedRowIndexes = self.selectedRowIndexes\n        self.reloadData()\n        self.selectRowIndexes(selectedRowIndexes, byExtendingSelection: true)\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Views/PrefPanel/InfoTimerView.swift",
    "content": "//\n//  InfoTimerView.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 19/03/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Cocoa\n\nclass InfoTimerView: NSView {\n    @IBOutlet var durationTimePicker: NSDatePicker!\n    @IBOutlet var withSecondsCheckbox: NSButton!\n    @IBOutlet var disableWhenElapsedCheckbox: NSButton!\n    @IBOutlet var replaceWithMessageCheckbox: NSButton!\n    @IBOutlet var customMessageTextField: NSTextField!\n\n    // Init(ish)\n    func setStates() {\n        durationTimePicker.dateValue = PrefsInfo.timer.duration\n        durationTimePicker.locale = Locale(identifier: \"fr_FR\")\n        withSecondsCheckbox.state = PrefsInfo.timer.showSeconds ? .on : .off\n        disableWhenElapsedCheckbox.state = PrefsInfo.timer.disableWhenElapsed ? .on : .off\n        replaceWithMessageCheckbox.state = PrefsInfo.timer.replaceWithMessage ? .on : .off\n        customMessageTextField.stringValue = PrefsInfo.timer.customMessage\n        customMessageTextField.isEnabled = PrefsInfo.timer.replaceWithMessage\n    }\n\n    @IBAction func durationChange(_ sender: NSDatePicker) {\n        PrefsInfo.timer.duration = sender.dateValue\n    }\n\n    @IBAction func withSecondsClick(_ sender: NSButton) {\n        let onState = sender.state == .on\n        PrefsInfo.timer.showSeconds = onState\n    }\n\n    @IBAction func disableWhenElapsedClick(_ sender: NSButton) {\n        let onState = sender.state == .on\n        PrefsInfo.timer.disableWhenElapsed = onState\n    }\n\n    @IBAction func replaceWithMessageClick(_ sender: NSButton) {\n        let onState = sender.state == .on\n        PrefsInfo.timer.replaceWithMessage = onState\n        customMessageTextField.isEnabled = onState\n    }\n\n    @IBAction func customMessageTextFieldChange(_ sender: NSTextField) {\n        PrefsInfo.timer.customMessage = sender.stringValue\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Views/PrefPanel/InfoWeatherView.swift",
    "content": "//\n//  InfoWeatherView.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 25/03/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Cocoa\n\nclass InfoWeatherView: NSView {\n    @IBOutlet var withCity: NSButton!\n    @IBOutlet var withWind: NSButton!\n    @IBOutlet var withHumidity: NSButton!\n    @IBOutlet var locationMode: NSPopUpButton!\n    @IBOutlet var locationString: NSTextField!\n    @IBOutlet var degreePopup: NSPopUpButton!\n    @IBOutlet var iconsPopup: NSPopUpButton!\n    @IBOutlet var locationLabel: NSTextField!\n    @IBOutlet var weatherModePopup: NSPopUpButton!\n\n    @IBOutlet var windModePopup: NSPopUpButton!\n\n    @IBOutlet weak var testButtonLocation: NSButton!\n    @IBOutlet weak var testButtonCity: NSButton!\n\n    // Init(ish)\n    func setStates() {\n        locationMode.selectItem(at: PrefsInfo.weather.locationMode.rawValue)\n        degreePopup.selectItem(at: PrefsInfo.weather.degree.rawValue)\n        iconsPopup.selectItem(at: PrefsInfo.weather.icons.rawValue)\n        weatherModePopup.selectItem(at: PrefsInfo.weather.mode.rawValue)\n        windModePopup.selectItem(at: PrefsInfo.weatherWindMode.rawValue)\n\n        if PrefsInfo.weather.degree == .fahrenheit {\n            windModePopup.isHidden = true\n        }\n\n        withCity.state = PrefsInfo.weather.showCity ? .on : .off\n        withWind.state = PrefsInfo.weather.showWind ? .on : .off\n        withHumidity.state = PrefsInfo.weather.showHumidity ? .on : .off\n\n        // Hide the flat color icons pre Big Sur as those are not available\n        if #available(macOS 11.0, *) {\n        } else {\n            iconsPopup.item(at: 1)?.isHidden = true\n        }\n        locationString.stringValue = PrefsInfo.weather.locationString\n        locationLabel.stringValue = \"\"\n        locationString.delegate = self\n        updateLocationMode()\n    }\n\n    @IBAction func windModePopupChange(_ sender: NSPopUpButton) {\n        PrefsInfo.weatherWindMode = InfoWeatherWind(rawValue: sender.indexOfSelectedItem)!\n    }\n\n    @IBAction func weatherModePopupChange(_ sender: NSPopUpButton) {\n        PrefsInfo.weather.mode = InfoWeatherMode(rawValue: sender.indexOfSelectedItem)!\n    }\n\n    @IBAction func locationModeChange(_ sender: NSPopUpButton) {\n        PrefsInfo.weather.locationMode = InfoLocationMode(rawValue: sender.indexOfSelectedItem)!\n        \n        if PrefsInfo.weather.locationMode == .useCurrent {\n            // Get the location\n            let location = Locations.sharedInstance\n\n            location.getCoordinates(failure: { (_) in\n                // swiftlint:disable:next line_length\n                Aerial.helper.showInfoAlert(title: \"Could not get your location\", text: \"Make sure you enabled location services on your Mac (and Wi-Fi!), and that Aerial (or legacyScreenSaver on macOS 10.15 and later) is allowed to use your location. If you use Aerial Companion, you will also need also allow location services for it.\", button1: \"OK\", caution: true)\n            }, success: { (coordinates) in\n                self.locationLabel.stringValue = \"Location found (\\(String(format: \"%.2f\", coordinates.latitude)), \\(String(format: \"%.2f\", coordinates.longitude)))\"\n                \n            })\n        }\n        \n        updateLocationMode()\n    }\n\n    @IBAction func withCityChange(_ sender: NSButton) {\n        let onState = sender.state == .on\n        PrefsInfo.weather.showCity = onState\n    }\n\n    @IBAction func withWindChange(_ sender: NSButton) {\n        let onState = sender.state == .on\n        PrefsInfo.weather.showWind = onState\n    }\n\n    @IBAction func withHumidityChange(_ sender: NSButton) {\n        let onState = sender.state == .on\n        PrefsInfo.weather.showHumidity = onState\n    }\n\n    func updateLocationMode() {\n        if PrefsInfo.weather.locationMode == .manuallySpecify {\n            locationString.isHidden = false\n            testButtonLocation.isHidden = true\n            testButtonCity.isHidden = false\n        } else {\n            locationString.isHidden = true\n            testButtonLocation.isHidden = false\n            testButtonCity.isHidden = true\n        }\n    }\n\n    @IBAction func iconsChange(_ sender: NSPopUpButton) {\n        PrefsInfo.weather.icons = InfoIconsWeather(rawValue: sender.indexOfSelectedItem)!\n    }\n\n    @IBAction func degreePopupChange(_ sender: NSPopUpButton) {\n        PrefsInfo.weather.degree = InfoDegree(rawValue: sender.indexOfSelectedItem)!\n\n        if PrefsInfo.weather.degree == .fahrenheit {\n            windModePopup.isHidden = true\n        } else {\n            windModePopup.isHidden = false\n        }\n    }\n\n    @IBAction func locationStringChange(_ sender: NSTextField) {\n        PrefsInfo.weather.locationString = sender.stringValue\n    }\n\n    @IBAction func testLocationButtonClick(_ sender: NSButton) {\n        // Clear out weather from existing location\n        let cachedWeatherURL = URL(fileURLWithPath: Cache.supportPath, isDirectory: true).appendingPathComponent(\"Weather.json\")\n        let cachedWeatherForecastURL = URL(fileURLWithPath: Cache.supportPath, isDirectory: true).appendingPathComponent(\"Forecast.json\")\n        let fm = FileManager.default\n        \n        // Clear out current weather\n        if fm.fileExists(atPath: cachedWeatherURL.path){\n            do {\n                try fm.removeItem(atPath: cachedWeatherURL.path)\n            } catch {}\n        }\n        \n        // Clear out forecast\n        if fm.fileExists(atPath: cachedWeatherForecastURL.path) {\n            do {\n                try fm.removeItem(atPath: cachedWeatherForecastURL.path)\n            } catch {}\n        }\n        \n        if PrefsInfo.weather.mode == .current {\n            OpenWeather.fetch { result in\n                switch result {\n                case .success(let openWeather):\n                    let ovc = self.parentViewController as! OverlaysViewController\n                    ovc.openWeatherPreview(weather: openWeather)\n                    if let name = openWeather.name {\n                        self.locationLabel.stringValue = name\n                    }\n                case .failure(let error):\n                    if error == .cityNotFound {\n                        self.locationLabel.stringValue = \"City not found, make sure you don't use state abbreviations\"\n                    } else {\n                        self.locationLabel.stringValue = error.localizedDescription\n                    }\n                }\n            }\n        } else {\n            Forecast.fetch { result in\n                switch result {\n                case .success(let openWeather):\n                    let ovc = self.parentViewController as! OverlaysViewController\n                    ovc.openWeatherPreview(weather: openWeather)\n\n                    if let lat = openWeather.city?.coord?.lat,\n                       let lon = openWeather.city?.coord?.lon,\n                       let name = openWeather.city?.name {\n                        self.locationLabel.stringValue = name\n                            + \" lat: \" + String(format: \"%.2f\", lat)\n                            + \" lon: \" + String(format: \"%.2f\", lon)\n                    }\n                case .failure(let error):\n                    if error == .cityNotFound {\n                        self.locationLabel.stringValue = \"City not found, make sure you don't use state abbreviations\"\n                    } else {\n                        self.locationLabel.stringValue = error.localizedDescription\n                    }\n                }\n            }\n        }\n    }\n\n    @IBAction func openWeatherLogoButton(_ sender: Any) {\n        NSWorkspace.shared.open(URL(string: \"https://openweathermap.org/\")!)\n    }\n}\n\nextension InfoWeatherView: NSTextFieldDelegate {\n    // We need the delegate to intercept changes without the\n    // enter key being pressed on the textfield\n    func controlTextDidChange(_ obj: Notification) {\n        let textField = obj.object as! NSTextField\n        // Just in case...\n        if textField == locationString {\n            // print(textField.stringValue)\n            PrefsInfo.weather.locationString = textField.stringValue\n        }\n    }\n}\n\nextension NSView {\n    var parentViewController: NSViewController? {\n        sequence(first: self) { $0.nextResponder }\n            .first(where: { $0 is NSViewController })\n            .flatMap { $0 as? NSViewController }\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Views/PrefPanel/VideoHeaderView.swift",
    "content": "//\n//  VideoHeaderView.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 14/07/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Cocoa\nimport AppKit\n\nclass VideoHeaderView: NSView {\n\n    @IBOutlet weak var sectionTitle: NSTextField!\n\n    override func draw(_ dirtyRect: NSRect) {\n        super.draw(dirtyRect)\n        // NSColor(calibratedWhite: 0.8, alpha: 0.8).set()\n        // NSRectFillUsingOperation(dirtyRect, NSCompositingOperation.sourceOver)\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Views/PrefPanel/VideoViewItem.swift",
    "content": "//\n//  VideoViewItem.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 13/07/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Cocoa\n\nclass VideoViewItem: NSCollectionViewItem {\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n        view.wantsLayer = true\n    }\n\n    var video: AerialVideo? {\n        didSet {\n            guard isViewLoaded else { return }\n            if let video = video {\n                Thumbnails.get(forVideo: video) { [weak self] (img) in\n                    guard let _ = self else { return }\n                    if let img = img {\n                        self!.imageView?.image = img\n                    } else {\n                        self!.imageView?.image = nil\n                    }\n                }\n\n                if video.secondaryName != \"\" {\n                    textField?.stringValue = video.secondaryName\n                } else {\n                    textField?.stringValue = video.name\n                }\n\n            } else {\n                imageView?.image = nil\n                textField?.stringValue = \"\"\n            }\n        }\n    }\n    /*var videoFile: VideoFile? {\n        didSet {\n            guard isViewLoaded else { return }\n            if let videoFile = videoFile {\n                imageView.image = videoFile.thumba\n            }\n        }\n    }*/\n}\n"
  },
  {
    "path": "Aerial/Source/Views/Sources/ActionCellView.swift",
    "content": "//\n//  ActionCellView.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 31/07/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Cocoa\n\nclass ActionCellView: NSTableCellView {\n    @IBOutlet var actionButton: NSButton!\n    @IBOutlet var spinner: NSProgressIndicator!\n    var source: Source?\n    @IBAction func actionButton(_ sender: NSButton) {\n        if let source = source {\n            if source.type == .local {\n                NSWorkspace.shared.selectFile(nil, inFileViewerRootedAtPath: Cache.supportPath.appending(\"/\"+source.name))\n            } else {\n                if source.isCachable {\n                    Cache.ensureDownload {\n                        sender.isHidden = true\n                        self.spinner.isHidden = false\n                        self.spinner.startAnimation(self)\n\n                        for video in VideoList.instance.videos.filter({ $0.source.name == source.name && !$0.isAvailableOffline }) {\n                            VideoManager.sharedInstance.queueDownload(video)\n                        }\n                    }\n                } else {\n                    sender.isHidden = true\n                    spinner.isHidden = false\n                    spinner.startAnimation(self)\n\n                    for video in VideoList.instance.videos.filter({ $0.source.name == source.name && !$0.isAvailableOffline }) {\n                        VideoManager.sharedInstance.queueDownload(video)\n                    }\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Views/Sources/CheckboxCellView.swift",
    "content": "//\n//  CheckboxCellView.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 09/07/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Cocoa\n// swiftlint:disable class_delegate_protocol weak_delegate\n\n/// A set of methods that `CheckboxCelView` use to communicate changes to another object\nprotocol CheckboxCellViewDelegate {\n    func checkboxCellView(_ cell: CheckboxCellView, didChangeState state: NSControl.StateValue)\n}\n\nclass CheckboxCellView: NSTableCellView {\n\n    /// The checkbox button\n    @IBOutlet weak var checkboxButton: NSButton!\n\n    /// The item that represent the row in the outline view\n    /// We may potentially use this cell for multiple outline views so let's make it generic\n    var item: Any?\n\n    /// The delegate of the cell\n    var delegate: CheckboxCellViewDelegate?\n\n    override func awakeFromNib() {\n        checkboxButton.target = self\n        checkboxButton.action = #selector(self.didChangeState(_:))\n    }\n\n    /// Notify the delegate that the checkbox's state has changed\n    @objc private func didChangeState(_ sender: NSObject) {\n        delegate?.checkboxCellView(self, didChangeState: checkboxButton.state)\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Views/Sources/DescriptionCellView.swift",
    "content": "//\n//  DescriptionCellView.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 09/07/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Cocoa\n\nclass DescriptionCellView: NSTableCellView {\n\n    @IBOutlet weak var titleLabel: NSTextField!\n    @IBOutlet weak var descriptionLabel: NSTextField!\n    @IBOutlet weak var lastUpdatedLabel: NSTextField!\n    @IBOutlet weak var videoCount: NSTextField!\n    @IBOutlet weak var imageScene1: NSImageView!\n    @IBOutlet weak var imageScene2: NSImageView!\n    @IBOutlet weak var imageScene3: NSImageView!\n    @IBOutlet weak var imageScene4: NSImageView!\n    @IBOutlet weak var imageScene5: NSImageView!\n    @IBOutlet weak var imageScene6: NSImageView!\n    @IBOutlet weak var imageFilm: NSImageView!\n    @IBOutlet weak var licenseButton: NSButton!\n    @IBOutlet weak var moreButton: NSButton!\n    @IBOutlet weak var refreshNowButton: NSButton!\n\n    /// The item that represent the row in the outline view\n    /// We may potentially use this cell for multiple outline views so let's make it generic\n    var item: Any?\n\n    /// The delegate of the cell\n    // var delegate: CheckboxCellViewDelegate?\n\n    override func awakeFromNib() {\n        imageScene1.image = Aerial.helper.getMiniSymbol(\"flame\")\n        imageScene2.image = Aerial.helper.getMiniSymbol(\"tram.fill\")\n        imageScene3.image = Aerial.helper.getMiniSymbol(\"sparkles\")\n        imageScene4.image = Aerial.helper.getMiniSymbol(\"helm\")\n        imageScene5.image = Aerial.helper.getMiniSymbol(\"helm\")\n        imageScene6.image = Aerial.helper.getMiniSymbol(\"helm\")\n        imageFilm.image = Aerial.helper.getMiniSymbol(\"film\")\n\n        // imageScene1.\n        // checkboxButton.target = self\n        // checkboxButton.action = #selector(self.didChangeState(_:))\n    }\n\n    /// Notify the delegate that the checkbox's state has changed\n    @objc private func didChangeState(_ sender: NSObject) {\n        // delegate?.checkboxCellView(self, didChangeState: checkboxButton.state)\n    }\n\n    @IBAction func licenseButtonClick(_ sender: NSButton) {\n        if let source = item as? Source {\n            let workspace = NSWorkspace.shared\n            let url = URL(string: source.license)!\n            workspace.open(url)\n        }\n    }\n\n    @IBAction func moreButtonClick(_ sender: NSButton) {\n        if let source = item as? Source {\n            let workspace = NSWorkspace.shared\n            let url = URL(string: source.more)!\n            workspace.open(url)\n        }\n    }\n\n    @IBAction func refreshNowButtonClick(_ sender: NSButton) {\n        if let source = item as? Source {\n            if source.isCachable {\n                debugLog(\"Refreshing cacheable source\")\n                VideoList.instance.downloadSource(source: source)\n            } else if source.type == .local {\n                debugLog(\"Checking local directory\")\n                SourceList.updateLocalSource(source: source, reload: true)\n            } else {\n                debugLog(\"Refreshing non-cacheable source\")\n                VideoList.instance.downloadSource(source: source)\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Aerial/Source/Views/Sources/SourceOutlineView.swift",
    "content": "//\n//  SourceOutlineView.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 16/08/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Cocoa\n\nprotocol SourceOutlineViewDelegate: NSOutlineViewDelegate {\n    func outlineView(outlineView: NSOutlineView, menuForItem item: Any) -> NSMenu?\n}\n\nclass SourceOutlineView: NSOutlineView {\n\n    override func menu(for event: NSEvent) -> NSMenu? {\n        let point = self.convert(event.locationInWindow, from: nil)\n        let row = self.row(at: point)\n\n        if let item = self.item(atRow: row) {\n            return (self.delegate as! SourceOutlineViewDelegate).outlineView(outlineView: self, menuForItem: item)\n\n        }\n\n        return nil\n    }\n\n}\n"
  },
  {
    "path": "Aerial copy-Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>com.JohnCoates.Aerial</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>BNDL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>$(MARKETING_VERSION)</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleVersion</key>\n\t<string>$(CURRENT_PROJECT_VERSION)</string>\n\t<key>LSApplicationCategoryType</key>\n\t<string></string>\n\t<key>LSMinimumSystemVersion</key>\n\t<string>${MACOSX_DEPLOYMENT_TARGET}</string>\n\t<key>NSAppTransportSecurity</key>\n\t<dict>\n\t\t<key>NSAllowsArbitraryLoads</key>\n\t\t<true/>\n\t</dict>\n\t<key>NSLocationAlwaysUsageDescription</key>\n\t<string>Aerial uses location services to calculate Sunset and Sunrise times from your position</string>\n\t<key>NSLocationWhenInUseUsageDescription</key>\n\t<string>Aerial uses location services to calculate Sunset and Sunrise times from your position</string>\n\t<key>NSPrincipalClass</key>\n\t<string>AerialView</string>\n\t<key>SUFeedURL</key>\n\t<string>https://raw.githubusercontent.com/JohnCoates/Aerial/master/appcast.xml</string>\n\t<key>SUPublicEDKey</key>\n\t<string>fbiQGEFq55xl4bjwj2/SpIO4JMsKmEyhHEWlMMueyDY=</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "Aerial.xcodeproj/project.pbxproj",
    "content": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section */\n\t\t0300109724D6EF4C0092AE68 /* AVPlayerItem+vibrance.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0300109624D6EF4C0092AE68 /* AVPlayerItem+vibrance.swift */; };\n\t\t0300109824D6EF4C0092AE68 /* AVPlayerItem+vibrance.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0300109624D6EF4C0092AE68 /* AVPlayerItem+vibrance.swift */; };\n\t\t0300109924D6EF4C0092AE68 /* AVPlayerItem+vibrance.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0300109624D6EF4C0092AE68 /* AVPlayerItem+vibrance.swift */; };\n\t\t030010A224D706DB0092AE68 /* SidebarOutlineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 030010A124D706DB0092AE68 /* SidebarOutlineView.swift */; };\n\t\t030010A324D706DB0092AE68 /* SidebarOutlineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 030010A124D706DB0092AE68 /* SidebarOutlineView.swift */; };\n\t\t030010A424D706DB0092AE68 /* SidebarOutlineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 030010A124D706DB0092AE68 /* SidebarOutlineView.swift */; };\n\t\t030010A624D718D30092AE68 /* slider.horizontal.3.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 030010A524D718D30092AE68 /* slider.horizontal.3.pdf */; };\n\t\t030010A724D718D30092AE68 /* slider.horizontal.3.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 030010A524D718D30092AE68 /* slider.horizontal.3.pdf */; };\n\t\t030010A824D718D30092AE68 /* slider.horizontal.3.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 030010A524D718D30092AE68 /* slider.horizontal.3.pdf */; };\n\t\t030010AB24D71EB20092AE68 /* FiltersViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 030010A924D71EB20092AE68 /* FiltersViewController.swift */; };\n\t\t030010AC24D71EB20092AE68 /* FiltersViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 030010A924D71EB20092AE68 /* FiltersViewController.swift */; };\n\t\t030010AD24D71EB20092AE68 /* FiltersViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 030010A924D71EB20092AE68 /* FiltersViewController.swift */; };\n\t\t030010AE24D71EB20092AE68 /* FiltersViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 030010AA24D71EB20092AE68 /* FiltersViewController.xib */; };\n\t\t030010AF24D71EB20092AE68 /* FiltersViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 030010AA24D71EB20092AE68 /* FiltersViewController.xib */; };\n\t\t030010B024D71EB20092AE68 /* FiltersViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 030010AA24D71EB20092AE68 /* FiltersViewController.xib */; };\n\t\t0300B7E924D1B536006132E5 /* person.3.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7CA24D1B531006132E5 /* person.3.pdf */; };\n\t\t0300B7EA24D1B536006132E5 /* person.3.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7CA24D1B531006132E5 /* person.3.pdf */; };\n\t\t0300B7EB24D1B536006132E5 /* person.3.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7CA24D1B531006132E5 /* person.3.pdf */; };\n\t\t0300B7EC24D1B536006132E5 /* bubble.left.and.bubble.right.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7CB24D1B531006132E5 /* bubble.left.and.bubble.right.pdf */; };\n\t\t0300B7ED24D1B536006132E5 /* bubble.left.and.bubble.right.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7CB24D1B531006132E5 /* bubble.left.and.bubble.right.pdf */; };\n\t\t0300B7EE24D1B536006132E5 /* bubble.left.and.bubble.right.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7CB24D1B531006132E5 /* bubble.left.and.bubble.right.pdf */; };\n\t\t0300B7EF24D1B536006132E5 /* helm.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7CC24D1B531006132E5 /* helm.pdf */; };\n\t\t0300B7F024D1B536006132E5 /* helm.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7CC24D1B531006132E5 /* helm.pdf */; };\n\t\t0300B7F124D1B536006132E5 /* helm.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7CC24D1B531006132E5 /* helm.pdf */; };\n\t\t0300B7F224D1B536006132E5 /* gear.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7CD24D1B532006132E5 /* gear.pdf */; };\n\t\t0300B7F324D1B536006132E5 /* gear.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7CD24D1B532006132E5 /* gear.pdf */; };\n\t\t0300B7F424D1B536006132E5 /* gear.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7CD24D1B532006132E5 /* gear.pdf */; };\n\t\t0300B7F524D1B536006132E5 /* eye.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7CE24D1B532006132E5 /* eye.pdf */; };\n\t\t0300B7F624D1B536006132E5 /* eye.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7CE24D1B532006132E5 /* eye.pdf */; };\n\t\t0300B7F724D1B536006132E5 /* eye.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7CE24D1B532006132E5 /* eye.pdf */; };\n\t\t0300B7F824D1B536006132E5 /* text.bubble.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7CF24D1B532006132E5 /* text.bubble.pdf */; };\n\t\t0300B7F924D1B536006132E5 /* text.bubble.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7CF24D1B532006132E5 /* text.bubble.pdf */; };\n\t\t0300B7FA24D1B536006132E5 /* text.bubble.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7CF24D1B532006132E5 /* text.bubble.pdf */; };\n\t\t0300B7FB24D1B536006132E5 /* circle.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7D024D1B532006132E5 /* circle.pdf */; };\n\t\t0300B7FC24D1B536006132E5 /* circle.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7D024D1B532006132E5 /* circle.pdf */; };\n\t\t0300B7FD24D1B536006132E5 /* circle.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7D024D1B532006132E5 /* circle.pdf */; };\n\t\t0300B7FE24D1B536006132E5 /* star.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7D124D1B532006132E5 /* star.pdf */; };\n\t\t0300B7FF24D1B536006132E5 /* star.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7D124D1B532006132E5 /* star.pdf */; };\n\t\t0300B80024D1B536006132E5 /* star.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7D124D1B532006132E5 /* star.pdf */; };\n\t\t0300B80124D1B536006132E5 /* clock.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7D224D1B532006132E5 /* clock.pdf */; };\n\t\t0300B80224D1B536006132E5 /* clock.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7D224D1B532006132E5 /* clock.pdf */; };\n\t\t0300B80324D1B536006132E5 /* clock.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7D224D1B532006132E5 /* clock.pdf */; };\n\t\t0300B80424D1B536006132E5 /* sparkles.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7D324D1B532006132E5 /* sparkles.pdf */; };\n\t\t0300B80524D1B536006132E5 /* sparkles.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7D324D1B532006132E5 /* sparkles.pdf */; };\n\t\t0300B80624D1B536006132E5 /* sparkles.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7D324D1B532006132E5 /* sparkles.pdf */; };\n\t\t0300B80724D1B536006132E5 /* film.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7D424D1B533006132E5 /* film.pdf */; };\n\t\t0300B80824D1B536006132E5 /* film.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7D424D1B533006132E5 /* film.pdf */; };\n\t\t0300B80924D1B536006132E5 /* film.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7D424D1B533006132E5 /* film.pdf */; };\n\t\t0300B80A24D1B536006132E5 /* eye.slash.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7D524D1B533006132E5 /* eye.slash.pdf */; };\n\t\t0300B80B24D1B536006132E5 /* eye.slash.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7D524D1B533006132E5 /* eye.slash.pdf */; };\n\t\t0300B80C24D1B536006132E5 /* eye.slash.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7D524D1B533006132E5 /* eye.slash.pdf */; };\n\t\t0300B80D24D1B536006132E5 /* info.circle.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7D624D1B533006132E5 /* info.circle.pdf */; };\n\t\t0300B80E24D1B536006132E5 /* info.circle.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7D624D1B533006132E5 /* info.circle.pdf */; };\n\t\t0300B80F24D1B536006132E5 /* info.circle.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7D624D1B533006132E5 /* info.circle.pdf */; };\n\t\t0300B81024D1B536006132E5 /* regular.moon.stars.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7D724D1B533006132E5 /* regular.moon.stars.pdf */; };\n\t\t0300B81124D1B536006132E5 /* regular.moon.stars.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7D724D1B533006132E5 /* regular.moon.stars.pdf */; };\n\t\t0300B81224D1B536006132E5 /* regular.moon.stars.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7D724D1B533006132E5 /* regular.moon.stars.pdf */; };\n\t\t0300B81324D1B536006132E5 /* antenna.radiowaves.left.and.right.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7D824D1B533006132E5 /* antenna.radiowaves.left.and.right.pdf */; };\n\t\t0300B81424D1B536006132E5 /* antenna.radiowaves.left.and.right.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7D824D1B533006132E5 /* antenna.radiowaves.left.and.right.pdf */; };\n\t\t0300B81524D1B536006132E5 /* antenna.radiowaves.left.and.right.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7D824D1B533006132E5 /* antenna.radiowaves.left.and.right.pdf */; };\n\t\t0300B81624D1B536006132E5 /* sunset.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7D924D1B533006132E5 /* sunset.pdf */; };\n\t\t0300B81724D1B536006132E5 /* sunset.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7D924D1B533006132E5 /* sunset.pdf */; };\n\t\t0300B81824D1B536006132E5 /* sunset.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7D924D1B533006132E5 /* sunset.pdf */; };\n\t\t0300B81924D1B536006132E5 /* tram.fill.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7DA24D1B534006132E5 /* tram.fill.pdf */; };\n\t\t0300B81A24D1B536006132E5 /* tram.fill.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7DA24D1B534006132E5 /* tram.fill.pdf */; };\n\t\t0300B81B24D1B536006132E5 /* tram.fill.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7DA24D1B534006132E5 /* tram.fill.pdf */; };\n\t\t0300B81C24D1B536006132E5 /* arrow.down.circle.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7DB24D1B534006132E5 /* arrow.down.circle.pdf */; };\n\t\t0300B81D24D1B536006132E5 /* arrow.down.circle.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7DB24D1B534006132E5 /* arrow.down.circle.pdf */; };\n\t\t0300B81E24D1B536006132E5 /* arrow.down.circle.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7DB24D1B534006132E5 /* arrow.down.circle.pdf */; };\n\t\t0300B81F24D1B536006132E5 /* flame.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7DC24D1B534006132E5 /* flame.pdf */; };\n\t\t0300B82024D1B536006132E5 /* flame.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7DC24D1B534006132E5 /* flame.pdf */; };\n\t\t0300B82124D1B536006132E5 /* flame.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7DC24D1B534006132E5 /* flame.pdf */; };\n\t\t0300B82224D1B536006132E5 /* regular.sun.min.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7DD24D1B534006132E5 /* regular.sun.min.pdf */; };\n\t\t0300B82324D1B536006132E5 /* regular.sun.min.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7DD24D1B534006132E5 /* regular.sun.min.pdf */; };\n\t\t0300B82424D1B536006132E5 /* regular.sun.min.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7DD24D1B534006132E5 /* regular.sun.min.pdf */; };\n\t\t0300B82524D1B536006132E5 /* mappin.and.ellipse.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7DE24D1B534006132E5 /* mappin.and.ellipse.pdf */; };\n\t\t0300B82624D1B536006132E5 /* mappin.and.ellipse.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7DE24D1B534006132E5 /* mappin.and.ellipse.pdf */; };\n\t\t0300B82724D1B536006132E5 /* mappin.and.ellipse.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7DE24D1B534006132E5 /* mappin.and.ellipse.pdf */; };\n\t\t0300B82824D1B536006132E5 /* arrow.down.circle.fill.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7DF24D1B534006132E5 /* arrow.down.circle.fill.pdf */; };\n\t\t0300B82924D1B536006132E5 /* arrow.down.circle.fill.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7DF24D1B534006132E5 /* arrow.down.circle.fill.pdf */; };\n\t\t0300B82A24D1B536006132E5 /* arrow.down.circle.fill.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7DF24D1B534006132E5 /* arrow.down.circle.fill.pdf */; };\n\t\t0300B82B24D1B536006132E5 /* location.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7E024D1B535006132E5 /* location.pdf */; };\n\t\t0300B82C24D1B536006132E5 /* location.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7E024D1B535006132E5 /* location.pdf */; };\n\t\t0300B82D24D1B536006132E5 /* location.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7E024D1B535006132E5 /* location.pdf */; };\n\t\t0300B82E24D1B536006132E5 /* tv.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7E124D1B535006132E5 /* tv.pdf */; };\n\t\t0300B82F24D1B536006132E5 /* tv.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7E124D1B535006132E5 /* tv.pdf */; };\n\t\t0300B83024D1B536006132E5 /* tv.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7E124D1B535006132E5 /* tv.pdf */; };\n\t\t0300B83124D1B536006132E5 /* sunrise.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7E224D1B535006132E5 /* sunrise.pdf */; };\n\t\t0300B83224D1B536006132E5 /* sunrise.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7E224D1B535006132E5 /* sunrise.pdf */; };\n\t\t0300B83324D1B536006132E5 /* sunrise.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7E224D1B535006132E5 /* sunrise.pdf */; };\n\t\t0300B83424D1B536006132E5 /* star.fill.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7E324D1B535006132E5 /* star.fill.pdf */; };\n\t\t0300B83524D1B536006132E5 /* star.fill.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7E324D1B535006132E5 /* star.fill.pdf */; };\n\t\t0300B83624D1B536006132E5 /* star.fill.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7E324D1B535006132E5 /* star.fill.pdf */; };\n\t\t0300B83724D1B536006132E5 /* regular.cloud.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7E424D1B535006132E5 /* regular.cloud.pdf */; };\n\t\t0300B83824D1B536006132E5 /* regular.cloud.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7E424D1B535006132E5 /* regular.cloud.pdf */; };\n\t\t0300B83924D1B536006132E5 /* regular.cloud.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7E424D1B535006132E5 /* regular.cloud.pdf */; };\n\t\t0300B83A24D1B536006132E5 /* regular.sun.max.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7E524D1B535006132E5 /* regular.sun.max.pdf */; };\n\t\t0300B83B24D1B536006132E5 /* regular.sun.max.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7E524D1B535006132E5 /* regular.sun.max.pdf */; };\n\t\t0300B83C24D1B536006132E5 /* regular.sun.max.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7E524D1B535006132E5 /* regular.sun.max.pdf */; };\n\t\t0300B83D24D1B536006132E5 /* dial.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7E624D1B536006132E5 /* dial.pdf */; };\n\t\t0300B83E24D1B536006132E5 /* dial.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7E624D1B536006132E5 /* dial.pdf */; };\n\t\t0300B83F24D1B536006132E5 /* dial.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7E624D1B536006132E5 /* dial.pdf */; };\n\t\t0300B84024D1B536006132E5 /* checkmark.circle.fill.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7E724D1B536006132E5 /* checkmark.circle.fill.pdf */; };\n\t\t0300B84124D1B536006132E5 /* checkmark.circle.fill.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7E724D1B536006132E5 /* checkmark.circle.fill.pdf */; };\n\t\t0300B84224D1B536006132E5 /* checkmark.circle.fill.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7E724D1B536006132E5 /* checkmark.circle.fill.pdf */; };\n\t\t0300B84324D1B536006132E5 /* square.and.arrow.down.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7E824D1B536006132E5 /* square.and.arrow.down.pdf */; };\n\t\t0300B84424D1B536006132E5 /* square.and.arrow.down.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7E824D1B536006132E5 /* square.and.arrow.down.pdf */; };\n\t\t0300B84524D1B536006132E5 /* square.and.arrow.down.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0300B7E824D1B536006132E5 /* square.and.arrow.down.pdf */; };\n\t\t0300B84924D1FD24006132E5 /* FirstSetupWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0300B84724D1FD24006132E5 /* FirstSetupWindowController.swift */; };\n\t\t0300B84A24D1FD24006132E5 /* FirstSetupWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0300B84724D1FD24006132E5 /* FirstSetupWindowController.swift */; };\n\t\t0300B84B24D1FD24006132E5 /* FirstSetupWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0300B84724D1FD24006132E5 /* FirstSetupWindowController.swift */; };\n\t\t0300B84C24D1FD24006132E5 /* FirstSetupWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0300B84824D1FD24006132E5 /* FirstSetupWindowController.xib */; };\n\t\t0300B84D24D1FD24006132E5 /* FirstSetupWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0300B84824D1FD24006132E5 /* FirstSetupWindowController.xib */; };\n\t\t0300B84E24D1FD24006132E5 /* FirstSetupWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0300B84824D1FD24006132E5 /* FirstSetupWindowController.xib */; };\n\t\t0300B86124D2052B006132E5 /* WelcomeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0300B85F24D2052B006132E5 /* WelcomeViewController.swift */; };\n\t\t0300B86224D2052B006132E5 /* WelcomeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0300B85F24D2052B006132E5 /* WelcomeViewController.swift */; };\n\t\t0300B86324D2052B006132E5 /* WelcomeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0300B85F24D2052B006132E5 /* WelcomeViewController.swift */; };\n\t\t0300B86424D2052B006132E5 /* WelcomeViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0300B86024D2052B006132E5 /* WelcomeViewController.xib */; };\n\t\t0300B86524D2052B006132E5 /* WelcomeViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0300B86024D2052B006132E5 /* WelcomeViewController.xib */; };\n\t\t0300B86624D2052B006132E5 /* WelcomeViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0300B86024D2052B006132E5 /* WelcomeViewController.xib */; };\n\t\t0300B86924D20B12006132E5 /* NextViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0300B86724D20B12006132E5 /* NextViewController.swift */; };\n\t\t0300B86A24D20B12006132E5 /* NextViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0300B86724D20B12006132E5 /* NextViewController.swift */; };\n\t\t0300B86B24D20B12006132E5 /* NextViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0300B86724D20B12006132E5 /* NextViewController.swift */; };\n\t\t0300B86C24D20B12006132E5 /* NextViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0300B86824D20B12006132E5 /* NextViewController.xib */; };\n\t\t0300B86D24D20B12006132E5 /* NextViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0300B86824D20B12006132E5 /* NextViewController.xib */; };\n\t\t0300B86E24D20B12006132E5 /* NextViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0300B86824D20B12006132E5 /* NextViewController.xib */; };\n\t\t030473CB24BCA9A40094A1A6 /* VideoViewItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 030473C924BCA9A40094A1A6 /* VideoViewItem.swift */; };\n\t\t030473CC24BCA9A40094A1A6 /* VideoViewItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 030473C924BCA9A40094A1A6 /* VideoViewItem.swift */; };\n\t\t030473CD24BCA9A40094A1A6 /* VideoViewItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 030473C924BCA9A40094A1A6 /* VideoViewItem.swift */; };\n\t\t03047A5424D2DD8E000EFE62 /* NSMenuItem+icons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03047A5324D2DD8E000EFE62 /* NSMenuItem+icons.swift */; };\n\t\t03047A5524D2DD8E000EFE62 /* NSMenuItem+icons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03047A5324D2DD8E000EFE62 /* NSMenuItem+icons.swift */; };\n\t\t03047A5624D2DD8E000EFE62 /* NSMenuItem+icons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03047A5324D2DD8E000EFE62 /* NSMenuItem+icons.swift */; };\n\t\t0306336823A1012200046A59 /* LocationLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0306336723A1012200046A59 /* LocationLayer.swift */; };\n\t\t0306336923A1026800046A59 /* LocationLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0306336723A1012200046A59 /* LocationLayer.swift */; };\n\t\t0306336B23A142FA00046A59 /* LayerOffsets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0306336A23A142FA00046A59 /* LayerOffsets.swift */; };\n\t\t0306336C23A143D900046A59 /* LayerOffsets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0306336A23A142FA00046A59 /* LayerOffsets.swift */; };\n\t\t0306336E23A15FA900046A59 /* AnimationTextLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0306336D23A15FA900046A59 /* AnimationTextLayer.swift */; };\n\t\t03075EB124ED794F00FDBE48 /* trash.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03075EA824ED794F00FDBE48 /* trash.pdf */; };\n\t\t03075EB224ED794F00FDBE48 /* trash.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03075EA824ED794F00FDBE48 /* trash.pdf */; };\n\t\t03075EB324ED794F00FDBE48 /* trash.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03075EA824ED794F00FDBE48 /* trash.pdf */; };\n\t\t03075EB424ED794F00FDBE48 /* textformat.alt.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03075EB024ED794F00FDBE48 /* textformat.alt.pdf */; };\n\t\t03075EB524ED794F00FDBE48 /* textformat.alt.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03075EB024ED794F00FDBE48 /* textformat.alt.pdf */; };\n\t\t03075EB624ED794F00FDBE48 /* textformat.alt.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03075EB024ED794F00FDBE48 /* textformat.alt.pdf */; };\n\t\t030A0F29245C7C7D009E1D97 /* BatteryIconLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 030A0F28245C7C7D009E1D97 /* BatteryIconLayer.swift */; };\n\t\t030A0F2A245C7C7D009E1D97 /* BatteryIconLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 030A0F28245C7C7D009E1D97 /* BatteryIconLayer.swift */; };\n\t\t030D9B7C21551A8D00961E95 /* AerialPlayerItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA7E2E5D1FC62E8B00E5F320 /* AerialPlayerItem.swift */; };\n\t\t030DDA902423C3BE0072D5C9 /* InfoTimerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 030DDA8F2423C3BE0072D5C9 /* InfoTimerView.swift */; };\n\t\t0313329C24BF3FA700C84A05 /* SidebarViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0313329A24BF3FA700C84A05 /* SidebarViewController.swift */; };\n\t\t0313329D24BF3FA700C84A05 /* SidebarViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0313329A24BF3FA700C84A05 /* SidebarViewController.swift */; };\n\t\t0313329E24BF3FA700C84A05 /* SidebarViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0313329A24BF3FA700C84A05 /* SidebarViewController.swift */; };\n\t\t0313329F24BF3FA700C84A05 /* SidebarViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0313329B24BF3FA700C84A05 /* SidebarViewController.xib */; };\n\t\t031332A024BF3FA700C84A05 /* SidebarViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0313329B24BF3FA700C84A05 /* SidebarViewController.xib */; };\n\t\t031332A124BF3FA700C84A05 /* SidebarViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0313329B24BF3FA700C84A05 /* SidebarViewController.xib */; };\n\t\t0313F9E622942AA500B074BB /* CustomVideos.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0313F9E522942AA500B074BB /* CustomVideos.xib */; };\n\t\t0313F9E822942B4500B074BB /* CustomVideoController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0313F9E722942B4500B074BB /* CustomVideoController.swift */; };\n\t\t0313F9E92294337F00B074BB /* CustomVideos.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0313F9E522942AA500B074BB /* CustomVideos.xib */; };\n\t\t0313F9EA2294338300B074BB /* CustomVideoController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0313F9E722942B4500B074BB /* CustomVideoController.swift */; };\n\t\t0313F9EC2294468600B074BB /* SeededGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0313F9EB2294468600B074BB /* SeededGenerator.swift */; };\n\t\t0313F9ED2294468600B074BB /* SeededGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0313F9EB2294468600B074BB /* SeededGenerator.swift */; };\n\t\t0313F9EF22955F3B00B074BB /* CustomVideoFolders.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0313F9EE22955F3B00B074BB /* CustomVideoFolders.swift */; };\n\t\t0313F9F022955F3B00B074BB /* CustomVideoFolders.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0313F9EE22955F3B00B074BB /* CustomVideoFolders.swift */; };\n\t\t0317C19C268B65D10082A40C /* Music.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0317C19B268B65D10082A40C /* Music.swift */; };\n\t\t0317C19D268B65D10082A40C /* Music.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0317C19B268B65D10082A40C /* Music.swift */; };\n\t\t0317C19E268B65D10082A40C /* Music.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0317C19B268B65D10082A40C /* Music.swift */; };\n\t\t031945F324CCC48C00F37B35 /* CreditsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 031945F124CCC48C00F37B35 /* CreditsViewController.swift */; };\n\t\t031945F424CCC48C00F37B35 /* CreditsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 031945F124CCC48C00F37B35 /* CreditsViewController.swift */; };\n\t\t031945F524CCC48C00F37B35 /* CreditsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 031945F124CCC48C00F37B35 /* CreditsViewController.swift */; };\n\t\t031945F624CCC48C00F37B35 /* CreditsViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 031945F224CCC48C00F37B35 /* CreditsViewController.xib */; };\n\t\t031945F724CCC48C00F37B35 /* CreditsViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 031945F224CCC48C00F37B35 /* CreditsViewController.xib */; };\n\t\t031945F824CCC48C00F37B35 /* CreditsViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 031945F224CCC48C00F37B35 /* CreditsViewController.xib */; };\n\t\t031945FB24CCC52600F37B35 /* HelpViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 031945F924CCC52600F37B35 /* HelpViewController.swift */; };\n\t\t031945FC24CCC52600F37B35 /* HelpViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 031945F924CCC52600F37B35 /* HelpViewController.swift */; };\n\t\t031945FD24CCC52600F37B35 /* HelpViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 031945F924CCC52600F37B35 /* HelpViewController.swift */; };\n\t\t031945FE24CCC52600F37B35 /* HelpViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 031945FA24CCC52600F37B35 /* HelpViewController.xib */; };\n\t\t031945FF24CCC52600F37B35 /* HelpViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 031945FA24CCC52600F37B35 /* HelpViewController.xib */; };\n\t\t0319460024CCC52600F37B35 /* HelpViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 031945FA24CCC52600F37B35 /* HelpViewController.xib */; };\n\t\t0319461024D1A09F00F37B35 /* icon-320@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 0319460824D1A09F00F37B35 /* icon-320@2x.png */; };\n\t\t0319461124D1A09F00F37B35 /* icon-320@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 0319460824D1A09F00F37B35 /* icon-320@2x.png */; };\n\t\t0319461224D1A09F00F37B35 /* icon-320@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 0319460824D1A09F00F37B35 /* icon-320@2x.png */; };\n\t\t031C5CB8268CA4E700CE35B4 /* ArtworkLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 031C5CB7268CA4E700CE35B4 /* ArtworkLayer.swift */; };\n\t\t031C5CB9268CA4E700CE35B4 /* ArtworkLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 031C5CB7268CA4E700CE35B4 /* ArtworkLayer.swift */; };\n\t\t031C5CBA268CA4E700CE35B4 /* ArtworkLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 031C5CB7268CA4E700CE35B4 /* ArtworkLayer.swift */; };\n\t\t031FB78B248A87330054BAFD /* PrefsCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 031FB78A248A87330054BAFD /* PrefsCache.swift */; };\n\t\t031FB7A2248A873C0054BAFD /* PrefsCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 031FB78A248A87330054BAFD /* PrefsCache.swift */; };\n\t\t0321A53324D44E80004F1975 /* ActionCellView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0321A53224D44E80004F1975 /* ActionCellView.swift */; };\n\t\t0321A53424D44E80004F1975 /* ActionCellView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0321A53224D44E80004F1975 /* ActionCellView.swift */; };\n\t\t0321A53524D44E80004F1975 /* ActionCellView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0321A53224D44E80004F1975 /* ActionCellView.swift */; };\n\t\t0321A53E24D4515B004F1975 /* folder.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0321A53D24D4515B004F1975 /* folder.pdf */; };\n\t\t0321A53F24D4515B004F1975 /* folder.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0321A53D24D4515B004F1975 /* folder.pdf */; };\n\t\t0321A54024D4515B004F1975 /* folder.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 0321A53D24D4515B004F1975 /* folder.pdf */; };\n\t\t0321A54424D5C863004F1975 /* NSButton+icons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0321A54324D5C863004F1975 /* NSButton+icons.swift */; };\n\t\t0321A54524D5C863004F1975 /* NSButton+icons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0321A54324D5C863004F1975 /* NSButton+icons.swift */; };\n\t\t0321A54624D5C863004F1975 /* NSButton+icons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0321A54324D5C863004F1975 /* NSButton+icons.swift */; };\n\t\t03233B68217272640077D3F9 /* PoiStringProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03233B67217272640077D3F9 /* PoiStringProvider.swift */; };\n\t\t03233B692172762C0077D3F9 /* PoiStringProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03233B67217272640077D3F9 /* PoiStringProvider.swift */; };\n\t\t032851F7260A4C2C00684A81 /* OneCall.swift in Sources */ = {isa = PBXBuildFile; fileRef = 032851F6260A4C2B00684A81 /* OneCall.swift */; };\n\t\t032851F8260A4C2C00684A81 /* OneCall.swift in Sources */ = {isa = PBXBuildFile; fileRef = 032851F6260A4C2B00684A81 /* OneCall.swift */; };\n\t\t032851F9260A4C2C00684A81 /* OneCall.swift in Sources */ = {isa = PBXBuildFile; fileRef = 032851F6260A4C2B00684A81 /* OneCall.swift */; };\n\t\t032851FB260A625100684A81 /* ForecastLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 032851FA260A625100684A81 /* ForecastLayer.swift */; };\n\t\t032851FC260A625100684A81 /* ForecastLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 032851FA260A625100684A81 /* ForecastLayer.swift */; };\n\t\t032851FD260A625100684A81 /* ForecastLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 032851FA260A625100684A81 /* ForecastLayer.swift */; };\n\t\t03298775274687340036D898 /* NowPlayingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03298773274687340036D898 /* NowPlayingViewController.swift */; };\n\t\t03298776274687340036D898 /* NowPlayingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03298773274687340036D898 /* NowPlayingViewController.swift */; };\n\t\t03298777274687340036D898 /* NowPlayingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03298773274687340036D898 /* NowPlayingViewController.swift */; };\n\t\t03298778274687340036D898 /* NowPlayingViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 03298774274687340036D898 /* NowPlayingViewController.xib */; };\n\t\t03298779274687340036D898 /* NowPlayingViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 03298774274687340036D898 /* NowPlayingViewController.xib */; };\n\t\t0329877A274687340036D898 /* NowPlayingViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 03298774274687340036D898 /* NowPlayingViewController.xib */; };\n\t\t032D1161239A7D82007E7756 /* Battery.swift in Sources */ = {isa = PBXBuildFile; fileRef = 032D1160239A7D82007E7756 /* Battery.swift */; };\n\t\t032D1162239A7E03007E7756 /* Battery.swift in Sources */ = {isa = PBXBuildFile; fileRef = 032D1160239A7D82007E7756 /* Battery.swift */; };\n\t\t032D1164239A7F0C007E7756 /* AerialView+Brightness.swift in Sources */ = {isa = PBXBuildFile; fileRef = 032D1163239A7F0C007E7756 /* AerialView+Brightness.swift */; };\n\t\t032D1165239A7F17007E7756 /* AerialView+Brightness.swift in Sources */ = {isa = PBXBuildFile; fileRef = 032D1163239A7F0C007E7756 /* AerialView+Brightness.swift */; };\n\t\t032E099E24C3897E00387230 /* AdvancedViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 032E099C24C3897E00387230 /* AdvancedViewController.swift */; };\n\t\t032E099F24C3897E00387230 /* AdvancedViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 032E099C24C3897E00387230 /* AdvancedViewController.swift */; };\n\t\t032E09A024C3897E00387230 /* AdvancedViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 032E099C24C3897E00387230 /* AdvancedViewController.swift */; };\n\t\t032E09A124C3897E00387230 /* AdvancedViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 032E099D24C3897E00387230 /* AdvancedViewController.xib */; };\n\t\t032E09A224C3897E00387230 /* AdvancedViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 032E099D24C3897E00387230 /* AdvancedViewController.xib */; };\n\t\t032E09A324C3897E00387230 /* AdvancedViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 032E099D24C3897E00387230 /* AdvancedViewController.xib */; };\n\t\t0332076D26D7C355001F9837 /* AVAsset+VideoOrientation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0332076C26D7C355001F9837 /* AVAsset+VideoOrientation.swift */; };\n\t\t0332076E26D7C355001F9837 /* AVAsset+VideoOrientation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0332076C26D7C355001F9837 /* AVAsset+VideoOrientation.swift */; };\n\t\t0332076F26D7C355001F9837 /* AVAsset+VideoOrientation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0332076C26D7C355001F9837 /* AVAsset+VideoOrientation.swift */; };\n\t\t0338119524C1D15B002E23E0 /* Aerial.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0338119424C1D15B002E23E0 /* Aerial.swift */; };\n\t\t0338119624C1D15B002E23E0 /* Aerial.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0338119424C1D15B002E23E0 /* Aerial.swift */; };\n\t\t0338119724C1D15B002E23E0 /* Aerial.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0338119424C1D15B002E23E0 /* Aerial.swift */; };\n\t\t033811B024C1E243002E23E0 /* InfoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 033811AE24C1E243002E23E0 /* InfoViewController.swift */; };\n\t\t033811B124C1E243002E23E0 /* InfoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 033811AE24C1E243002E23E0 /* InfoViewController.swift */; };\n\t\t033811B224C1E243002E23E0 /* InfoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 033811AE24C1E243002E23E0 /* InfoViewController.swift */; };\n\t\t033811B324C1E243002E23E0 /* InfoViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 033811AF24C1E243002E23E0 /* InfoViewController.xib */; };\n\t\t033811B424C1E243002E23E0 /* InfoViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 033811AF24C1E243002E23E0 /* InfoViewController.xib */; };\n\t\t033811B524C1E243002E23E0 /* InfoViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 033811AF24C1E243002E23E0 /* InfoViewController.xib */; };\n\t\t033842E124489D7300A2C523 /* WeatherLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 033842E024489D7300A2C523 /* WeatherLayer.swift */; };\n\t\t033842F824489EC600A2C523 /* WeatherLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 033842E024489D7300A2C523 /* WeatherLayer.swift */; };\n\t\t033D68812453080C0016F837 /* ConditionSymbolLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 033D68802453080C0016F837 /* ConditionSymbolLayer.swift */; };\n\t\t034116D323F9BD3100CD7674 /* PrefsUpdates.swift in Sources */ = {isa = PBXBuildFile; fileRef = 034116D223F9BD3100CD7674 /* PrefsUpdates.swift */; };\n\t\t034116D423F9BD3100CD7674 /* PrefsUpdates.swift in Sources */ = {isa = PBXBuildFile; fileRef = 034116D223F9BD3100CD7674 /* PrefsUpdates.swift */; };\n\t\t0343E9F92630590A00AC702F /* openweather_logo.png in Resources */ = {isa = PBXBuildFile; fileRef = 0343E9F82630590A00AC702F /* openweather_logo.png */; };\n\t\t0343E9FA2630590A00AC702F /* openweather_logo.png in Resources */ = {isa = PBXBuildFile; fileRef = 0343E9F82630590A00AC702F /* openweather_logo.png */; };\n\t\t0343E9FB2630590A00AC702F /* openweather_logo.png in Resources */ = {isa = PBXBuildFile; fileRef = 0343E9F82630590A00AC702F /* openweather_logo.png */; };\n\t\t0345872D2449C52F00C97D1B /* AnimatableLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0345872C2449C52F00C97D1B /* AnimatableLayer.swift */; };\n\t\t0345872E2449C59900C97D1B /* AnimatableLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0345872C2449C52F00C97D1B /* AnimatableLayer.swift */; };\n\t\t034587322449D8EB00C97D1B /* AnimationLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 034587312449D8EB00C97D1B /* AnimationLayer.swift */; };\n\t\t034587332449E22000C97D1B /* AnimationLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 034587312449D8EB00C97D1B /* AnimationLayer.swift */; };\n\t\t0345A24B24532E4600DD47CD /* ConditionSymbolLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 033D68802453080C0016F837 /* ConditionSymbolLayer.swift */; };\n\t\t0345CFED24BF43280001045C /* VideosViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0345CFEB24BF43280001045C /* VideosViewController.swift */; };\n\t\t0345CFEE24BF43280001045C /* VideosViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0345CFEB24BF43280001045C /* VideosViewController.swift */; };\n\t\t0345CFEF24BF43280001045C /* VideosViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0345CFEB24BF43280001045C /* VideosViewController.swift */; };\n\t\t0345CFF024BF43280001045C /* VideosViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0345CFEC24BF43280001045C /* VideosViewController.xib */; };\n\t\t0345CFF124BF43280001045C /* VideosViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0345CFEC24BF43280001045C /* VideosViewController.xib */; };\n\t\t0345CFF224BF43280001045C /* VideosViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0345CFEC24BF43280001045C /* VideosViewController.xib */; };\n\t\t0345D00A24BF4E8C0001045C /* Sidebar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0345D00924BF4E8C0001045C /* Sidebar.swift */; };\n\t\t0345D00B24BF4E8C0001045C /* Sidebar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0345D00924BF4E8C0001045C /* Sidebar.swift */; };\n\t\t0345D00C24BF4E8C0001045C /* Sidebar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0345D00924BF4E8C0001045C /* Sidebar.swift */; };\n\t\t0345D00E24C07CC70001045C /* VideoCellView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0345D00D24C07CC70001045C /* VideoCellView.swift */; };\n\t\t0345D00F24C07CC70001045C /* VideoCellView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0345D00D24C07CC70001045C /* VideoCellView.swift */; };\n\t\t0345D01024C07CC70001045C /* VideoCellView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0345D00D24C07CC70001045C /* VideoCellView.swift */; };\n\t\t0345EDE824C3239400C73038 /* DisplaysViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0345EDE624C3239400C73038 /* DisplaysViewController.swift */; };\n\t\t0345EDE924C3239400C73038 /* DisplaysViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0345EDE624C3239400C73038 /* DisplaysViewController.swift */; };\n\t\t0345EDEA24C3239400C73038 /* DisplaysViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0345EDE624C3239400C73038 /* DisplaysViewController.swift */; };\n\t\t0345EDEB24C3239400C73038 /* DisplaysViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0345EDE724C3239400C73038 /* DisplaysViewController.xib */; };\n\t\t0345EDEC24C3239400C73038 /* DisplaysViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0345EDE724C3239400C73038 /* DisplaysViewController.xib */; };\n\t\t0345EDED24C3239400C73038 /* DisplaysViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0345EDE724C3239400C73038 /* DisplaysViewController.xib */; };\n\t\t034A6DC224ACC7C800D62129 /* SourceList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 034A6DC124ACC7C800D62129 /* SourceList.swift */; };\n\t\t034A6DC424ACC80200D62129 /* Source.swift in Sources */ = {isa = PBXBuildFile; fileRef = 034A6DC324ACC80200D62129 /* Source.swift */; };\n\t\t034A6DC524ACC80B00D62129 /* Source.swift in Sources */ = {isa = PBXBuildFile; fileRef = 034A6DC324ACC80200D62129 /* Source.swift */; };\n\t\t034A6DC624AF3EC600D62129 /* SourceList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 034A6DC124ACC7C800D62129 /* SourceList.swift */; };\n\t\t034DEE2E24BF1BC700A2D3CD /* PanelWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 034DEE2C24BF1BC700A2D3CD /* PanelWindowController.swift */; };\n\t\t034DEE2F24BF1BC700A2D3CD /* PanelWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 034DEE2C24BF1BC700A2D3CD /* PanelWindowController.swift */; };\n\t\t034DEE3024BF1BC700A2D3CD /* PanelWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 034DEE2C24BF1BC700A2D3CD /* PanelWindowController.swift */; };\n\t\t034DEE3124BF1BC700A2D3CD /* PanelWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 034DEE2D24BF1BC700A2D3CD /* PanelWindowController.xib */; };\n\t\t034DEE3224BF1BC700A2D3CD /* PanelWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 034DEE2D24BF1BC700A2D3CD /* PanelWindowController.xib */; };\n\t\t034DEE3324BF1BC700A2D3CD /* PanelWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 034DEE2D24BF1BC700A2D3CD /* PanelWindowController.xib */; };\n\t\t034F29B723A7A93D004B34D5 /* InfoTableSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 034F29B623A7A93D004B34D5 /* InfoTableSource.swift */; };\n\t\t034F29B823A7A9B3004B34D5 /* InfoTableSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 034F29B623A7A93D004B34D5 /* InfoTableSource.swift */; };\n\t\t034F29BF23A7E28E004B34D5 /* PrefsInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 034F29BE23A7E28E004B34D5 /* PrefsInfo.swift */; };\n\t\t034F29C023A7E58C004B34D5 /* PrefsInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 034F29BE23A7E28E004B34D5 /* PrefsInfo.swift */; };\n\t\t0350CB7C279481F2005F8625 /* hu.json in Resources */ = {isa = PBXBuildFile; fileRef = 0350CB78279481F2005F8625 /* hu.json */; };\n\t\t0350CB7D279481F2005F8625 /* hu.json in Resources */ = {isa = PBXBuildFile; fileRef = 0350CB78279481F2005F8625 /* hu.json */; };\n\t\t0350CB7E279481F2005F8625 /* hu.json in Resources */ = {isa = PBXBuildFile; fileRef = 0350CB78279481F2005F8625 /* hu.json */; };\n\t\t03510C6B21834EB2008F74F2 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 03510C6A21834EB2008F74F2 /* IOKit.framework */; };\n\t\t03510C6C21834EFF008F74F2 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 03510C6A21834EB2008F74F2 /* IOKit.framework */; };\n\t\t03510C6F21834F38008F74F2 /* IOBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 03510C6E21834F38008F74F2 /* IOBridge.m */; };\n\t\t03510C7021834FC3008F74F2 /* Aerial-Bridging-Header.h in Headers */ = {isa = PBXBuildFile; fileRef = 03510C6D21834F38008F74F2 /* Aerial-Bridging-Header.h */; };\n\t\t03510C7121834FC7008F74F2 /* IOBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 03510C6E21834F38008F74F2 /* IOBridge.m */; };\n\t\t03510C732185EF76008F74F2 /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 03510C722185EF76008F74F2 /* CoreLocation.framework */; };\n\t\t03510C772185EF8F008F74F2 /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 03510C722185EF76008F74F2 /* CoreLocation.framework */; };\n\t\t0354D0E923F6C31800D86F9E /* InfoSettingsTableSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0354D0E823F6C31800D86F9E /* InfoSettingsTableSource.swift */; };\n\t\t0354D0EA23F6C3EE00D86F9E /* InfoSettingsTableSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0354D0E823F6C31800D86F9E /* InfoSettingsTableSource.swift */; };\n\t\t0354D0EC23F6CB7B00D86F9E /* InfoSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0354D0EB23F6CB7B00D86F9E /* InfoSettingsView.swift */; };\n\t\t0354D0ED23F6CB7B00D86F9E /* InfoSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0354D0EB23F6CB7B00D86F9E /* InfoSettingsView.swift */; };\n\t\t035D524F239AA31A00DC29DC /* AerialView+Player.swift in Sources */ = {isa = PBXBuildFile; fileRef = 035D524E239AA31A00DC29DC /* AerialView+Player.swift */; };\n\t\t035D5250239AA31A00DC29DC /* AerialView+Player.swift in Sources */ = {isa = PBXBuildFile; fileRef = 035D524E239AA31A00DC29DC /* AerialView+Player.swift */; };\n\t\t03608A2C22A56465008F08A2 /* HardwareDetection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03608A2B22A56465008F08A2 /* HardwareDetection.swift */; };\n\t\t03608A2D22A56465008F08A2 /* HardwareDetection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03608A2B22A56465008F08A2 /* HardwareDetection.swift */; };\n\t\t0361B9A823D732A300B6252D /* PrefsDisplays.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0361B9A723D732A300B6252D /* PrefsDisplays.swift */; };\n\t\t0361B9A923D732A300B6252D /* PrefsDisplays.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0361B9A723D732A300B6252D /* PrefsDisplays.swift */; };\n\t\t0361B9AB23D73D4500B6252D /* PrefsTime.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0361B9AA23D73D4500B6252D /* PrefsTime.swift */; };\n\t\t0361B9AC23D73D4500B6252D /* PrefsTime.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0361B9AA23D73D4500B6252D /* PrefsTime.swift */; };\n\t\t0369985D2196103300E359D3 /* missingvideos.json in Resources */ = {isa = PBXBuildFile; fileRef = 0369985C2196103300E359D3 /* missingvideos.json */; };\n\t\t0369985E2196129C00E359D3 /* missingvideos.json in Resources */ = {isa = PBXBuildFile; fileRef = 0369985C2196103300E359D3 /* missingvideos.json */; };\n\t\t036A57D523F30DD00009DC02 /* DownloadIndicatorLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 036A57D423F30DD00009DC02 /* DownloadIndicatorLayer.swift */; };\n\t\t036A57D623F30F490009DC02 /* DownloadIndicatorLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 036A57D423F30DD00009DC02 /* DownloadIndicatorLayer.swift */; };\n\t\t036A57D823F470940009DC02 /* InfoCountdownView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 036A57D723F470940009DC02 /* InfoCountdownView.swift */; };\n\t\t036A57D923F4747D0009DC02 /* InfoCountdownView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 036A57D723F470940009DC02 /* InfoCountdownView.swift */; };\n\t\t036A57DB23F5820A0009DC02 /* CountdownLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 036A57DA23F5820A0009DC02 /* CountdownLayer.swift */; };\n\t\t036A57DC23F5828E0009DC02 /* CountdownLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 036A57DA23F5820A0009DC02 /* CountdownLayer.swift */; };\n\t\t036A7E9B26370C260019186B /* Forecast.swift in Sources */ = {isa = PBXBuildFile; fileRef = 036A7E9A26370C260019186B /* Forecast.swift */; };\n\t\t036A7E9C26370C260019186B /* Forecast.swift in Sources */ = {isa = PBXBuildFile; fileRef = 036A7E9A26370C260019186B /* Forecast.swift */; };\n\t\t036A7E9D26370C260019186B /* Forecast.swift in Sources */ = {isa = PBXBuildFile; fileRef = 036A7E9A26370C260019186B /* Forecast.swift */; };\n\t\t0374C9FE247AC5BC002F29D3 /* Locations.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0374C9FD247AC5BC002F29D3 /* Locations.swift */; };\n\t\t0374C9FF247AC5BC002F29D3 /* Locations.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0374C9FD247AC5BC002F29D3 /* Locations.swift */; };\n\t\t037772E124E43AF300D81EEA /* TimeSetupViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 037772DF24E43AF300D81EEA /* TimeSetupViewController.swift */; };\n\t\t037772E224E43AF300D81EEA /* TimeSetupViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 037772DF24E43AF300D81EEA /* TimeSetupViewController.swift */; };\n\t\t037772E324E43AF300D81EEA /* TimeSetupViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 037772DF24E43AF300D81EEA /* TimeSetupViewController.swift */; };\n\t\t037772E424E43AF300D81EEA /* TimeSetupViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 037772E024E43AF300D81EEA /* TimeSetupViewController.xib */; };\n\t\t037772E524E43AF300D81EEA /* TimeSetupViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 037772E024E43AF300D81EEA /* TimeSetupViewController.xib */; };\n\t\t037772E624E43AF300D81EEA /* TimeSetupViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 037772E024E43AF300D81EEA /* TimeSetupViewController.xib */; };\n\t\t037772E824E44BB100D81EEA /* xmark.circle.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 037772E724E44BB100D81EEA /* xmark.circle.pdf */; };\n\t\t037772E924E44BB100D81EEA /* xmark.circle.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 037772E724E44BB100D81EEA /* xmark.circle.pdf */; };\n\t\t037772EA24E44BB100D81EEA /* xmark.circle.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 037772E724E44BB100D81EEA /* xmark.circle.pdf */; };\n\t\t037772ED24E44CE100D81EEA /* RecapViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 037772EB24E44CE100D81EEA /* RecapViewController.swift */; };\n\t\t037772EE24E44CE100D81EEA /* RecapViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 037772EB24E44CE100D81EEA /* RecapViewController.swift */; };\n\t\t037772EF24E44CE100D81EEA /* RecapViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 037772EB24E44CE100D81EEA /* RecapViewController.swift */; };\n\t\t037772F024E44CE100D81EEA /* RecapViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 037772EC24E44CE100D81EEA /* RecapViewController.xib */; };\n\t\t037772F124E44CE100D81EEA /* RecapViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 037772EC24E44CE100D81EEA /* RecapViewController.xib */; };\n\t\t037772F224E44CE100D81EEA /* RecapViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 037772EC24E44CE100D81EEA /* RecapViewController.xib */; };\n\t\t037772FC24E4668600D81EEA /* aspectratio.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 037772F424E4668600D81EEA /* aspectratio.pdf */; };\n\t\t037772FD24E4668600D81EEA /* aspectratio.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 037772F424E4668600D81EEA /* aspectratio.pdf */; };\n\t\t037772FE24E4668600D81EEA /* aspectratio.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 037772F424E4668600D81EEA /* aspectratio.pdf */; };\n\t\t0377BF8624BA15E700C33F9F /* btn_donate.png in Resources */ = {isa = PBXBuildFile; fileRef = 0377BF6F24BA15E600C33F9F /* btn_donate.png */; };\n\t\t0377BF8724BA15E700C33F9F /* btn_donate.png in Resources */ = {isa = PBXBuildFile; fileRef = 0377BF6F24BA15E600C33F9F /* btn_donate.png */; };\n\t\t0377BF8824BA15E700C33F9F /* btn_donate.png in Resources */ = {isa = PBXBuildFile; fileRef = 0377BF6F24BA15E600C33F9F /* btn_donate.png */; };\n\t\t0378985E24C35F8A009B9418 /* CacheViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0378985C24C35F8A009B9418 /* CacheViewController.swift */; };\n\t\t0378985F24C35F8A009B9418 /* CacheViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0378985C24C35F8A009B9418 /* CacheViewController.swift */; };\n\t\t0378986024C35F8A009B9418 /* CacheViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0378985C24C35F8A009B9418 /* CacheViewController.swift */; };\n\t\t0378986124C35F8A009B9418 /* CacheViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0378985D24C35F8A009B9418 /* CacheViewController.xib */; };\n\t\t0378986224C35F8A009B9418 /* CacheViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0378985D24C35F8A009B9418 /* CacheViewController.xib */; };\n\t\t0378986324C35F8A009B9418 /* CacheViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0378985D24C35F8A009B9418 /* CacheViewController.xib */; };\n\t\t0385FC59242B9AE1007E6513 /* APISecrets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0385FC58242B9AE1007E6513 /* APISecrets.swift */; };\n\t\t0385FC5A242B9AE1007E6513 /* APISecrets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0385FC58242B9AE1007E6513 /* APISecrets.swift */; };\n\t\t0385FC5D242B9F6E007E6513 /* InfoWeatherView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0385FC5C242B9F6E007E6513 /* InfoWeatherView.swift */; };\n\t\t0385FC6D242BA097007E6513 /* InfoWeatherView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0385FC5C242B9F6E007E6513 /* InfoWeatherView.swift */; };\n\t\t03893CB3217749F0008E7125 /* ErrorLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03893CB2217749F0008E7125 /* ErrorLog.swift */; };\n\t\t03893CB4217753AC008E7125 /* ErrorLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03893CB2217749F0008E7125 /* ErrorLog.swift */; };\n\t\t038C584723A9304800224630 /* InfoContainerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 038C584623A9304800224630 /* InfoContainerView.swift */; };\n\t\t038C584823A9308C00224630 /* InfoContainerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 038C584623A9304800224630 /* InfoContainerView.swift */; };\n\t\t038C584A23A9394000224630 /* InfoCommonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 038C584923A9394000224630 /* InfoCommonView.swift */; };\n\t\t038C584B23A9394000224630 /* InfoCommonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 038C584923A9394000224630 /* InfoCommonView.swift */; };\n\t\t038D2EBD23AB91C300CD91F7 /* InfoLocationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03A596D823AB8F000097EA66 /* InfoLocationView.swift */; };\n\t\t038D2EDE23B0FB0D00CD91F7 /* PrefsVideos.swift in Sources */ = {isa = PBXBuildFile; fileRef = 038D2EDD23B0FB0D00CD91F7 /* PrefsVideos.swift */; };\n\t\t038D2EDF23B0FB0D00CD91F7 /* PrefsVideos.swift in Sources */ = {isa = PBXBuildFile; fileRef = 038D2EDD23B0FB0D00CD91F7 /* PrefsVideos.swift */; };\n\t\t038D2EE423B6565900CD91F7 /* InfoBatteryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 038D2EE323B6565900CD91F7 /* InfoBatteryView.swift */; };\n\t\t038D2EE523B6565900CD91F7 /* InfoBatteryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 038D2EE323B6565900CD91F7 /* InfoBatteryView.swift */; };\n\t\t03933B8B24C3986800A98D94 /* SourcesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03933B8924C3986800A98D94 /* SourcesViewController.swift */; };\n\t\t03933B8C24C3986800A98D94 /* SourcesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03933B8924C3986800A98D94 /* SourcesViewController.swift */; };\n\t\t03933B8D24C3986800A98D94 /* SourcesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03933B8924C3986800A98D94 /* SourcesViewController.swift */; };\n\t\t03933B8E24C3986800A98D94 /* SourcesViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 03933B8A24C3986800A98D94 /* SourcesViewController.xib */; };\n\t\t03933B8F24C3986800A98D94 /* SourcesViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 03933B8A24C3986800A98D94 /* SourcesViewController.xib */; };\n\t\t03933B9024C3986800A98D94 /* SourcesViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 03933B8A24C3986800A98D94 /* SourcesViewController.xib */; };\n\t\t0393857A2175D4B80040B850 /* AVPlayerViewExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 039385792175D4B80040B850 /* AVPlayerViewExtension.swift */; };\n\t\t0393857B2175D4B80040B850 /* AVPlayerViewExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 039385792175D4B80040B850 /* AVPlayerViewExtension.swift */; };\n\t\t03958349217F4416008E8F9C /* Solar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03958348217F4416008E8F9C /* Solar.swift */; };\n\t\t0395834A217F442A008E8F9C /* Solar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03958348217F4416008E8F9C /* Solar.swift */; };\n\t\t0395835321807D1F008E8F9C /* thumbnail@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 0395835121807D1F008E8F9C /* thumbnail@2x.png */; };\n\t\t0395835421807D1F008E8F9C /* thumbnail@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 0395835121807D1F008E8F9C /* thumbnail@2x.png */; };\n\t\t0395835521807D1F008E8F9C /* thumbnail.png in Resources */ = {isa = PBXBuildFile; fileRef = 0395835221807D1F008E8F9C /* thumbnail.png */; };\n\t\t0395835621807D1F008E8F9C /* thumbnail.png in Resources */ = {isa = PBXBuildFile; fileRef = 0395835221807D1F008E8F9C /* thumbnail.png */; };\n\t\t0396D50B24B8B7ED00CC021B /* DisplayDetection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03D1E7892284471A00D10CF7 /* DisplayDetection.swift */; };\n\t\t0396D50C24B8B7ED00CC021B /* LayerOffsets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0306336A23A142FA00046A59 /* LayerOffsets.swift */; };\n\t\t0396D50D24B8B7ED00CC021B /* APISecrets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0385FC58242B9AE1007E6513 /* APISecrets.swift */; };\n\t\t0396D50E24B8B7ED00CC021B /* NightShift.swift in Sources */ = {isa = PBXBuildFile; fileRef = F00864B623AAE8E9003210EF /* NightShift.swift */; };\n\t\t0396D51024B8B7ED00CC021B /* CheckCellView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAC36F441BE1756D007F2A20 /* CheckCellView.swift */; };\n\t\t0396D51124B8B7ED00CC021B /* PrefsUpdates.swift in Sources */ = {isa = PBXBuildFile; fileRef = 034116D223F9BD3100CD7674 /* PrefsUpdates.swift */; };\n\t\t0396D51224B8B7ED00CC021B /* AerialView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAC36F431BE1756D007F2A20 /* AerialView.swift */; };\n\t\t0396D51324B8B7ED00CC021B /* PrefsCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 031FB78A248A87330054BAFD /* PrefsCache.swift */; };\n\t\t0396D51424B8B7ED00CC021B /* AVPlayerViewExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 039385792175D4B80040B850 /* AVPlayerViewExtension.swift */; };\n\t\t0396D51524B8B7ED00CC021B /* AsynchronousOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E8730E216501ED002B469B /* AsynchronousOperation.swift */; };\n\t\t0396D51624B8B7ED00CC021B /* LayerManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03BF51BB23A2643C008AD373 /* LayerManager.swift */; };\n\t\t0396D51824B8B7ED00CC021B /* IOBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 03510C6E21834F38008F74F2 /* IOBridge.m */; };\n\t\t0396D51924B8B7ED00CC021B /* DarkMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = F00864B323AAE7F0003210EF /* DarkMode.swift */; };\n\t\t0396D51A24B8B7ED00CC021B /* CustomVideoFolders.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0313F9EE22955F3B00B074BB /* CustomVideoFolders.swift */; };\n\t\t0396D51B24B8B7ED00CC021B /* InfoTimerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 030DDA8F2423C3BE0072D5C9 /* InfoTimerView.swift */; };\n\t\t0396D51D24B8B7ED00CC021B /* MessageLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03BF51BE23A274CA008AD373 /* MessageLayer.swift */; };\n\t\t0396D51E24B8B7ED00CC021B /* InfoCommonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 038C584923A9394000224630 /* InfoCommonView.swift */; };\n\t\t0396D51F24B8B7ED00CC021B /* AerialView+Brightness.swift in Sources */ = {isa = PBXBuildFile; fileRef = 032D1163239A7F0C007E7756 /* AerialView+Brightness.swift */; };\n\t\t0396D52124B8B7ED00CC021B /* Locations.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0374C9FD247AC5BC002F29D3 /* Locations.swift */; };\n\t\t0396D52224B8B7ED00CC021B /* VideoCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAF450231BE2D2FD00C1F98A /* VideoCache.swift */; };\n\t\t0396D52324B8B7ED00CC021B /* BatteryIconLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 030A0F28245C7C7D009E1D97 /* BatteryIconLayer.swift */; };\n\t\t0396D52424B8B7ED00CC021B /* PrefsDisplays.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0361B9A723D732A300B6252D /* PrefsDisplays.swift */; };\n\t\t0396D52624B8B7ED00CC021B /* Cache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03DC004D248BC5A4005DB0F4 /* Cache.swift */; };\n\t\t0396D52824B8B7ED00CC021B /* AnimationTextLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0306336D23A15FA900046A59 /* AnimationTextLayer.swift */; };\n\t\t0396D52924B8B7ED00CC021B /* InfoWeatherView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0385FC5C242B9F6E007E6513 /* InfoWeatherView.swift */; };\n\t\t0396D52B24B8B7ED00CC021B /* SeededGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0313F9EB2294468600B074BB /* SeededGenerator.swift */; };\n\t\t0396D52C24B8B7ED00CC021B /* InfoDateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03FA49B32428EE3300863AF6 /* InfoDateView.swift */; };\n\t\t0396D52D24B8B7ED00CC021B /* ManifestLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAC36F661BE1778C007F2A20 /* ManifestLoader.swift */; };\n\t\t0396D52E24B8B7ED00CC021B /* TimerLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03FA49A02423DA1F00863AF6 /* TimerLayer.swift */; };\n\t\t0396D52F24B8B7ED00CC021B /* Source.swift in Sources */ = {isa = PBXBuildFile; fileRef = 034A6DC324ACC80200D62129 /* Source.swift */; };\n\t\t0396D53024B8B7ED00CC021B /* PrefsInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 034F29BE23A7E28E004B34D5 /* PrefsInfo.swift */; };\n\t\t0396D53124B8B7ED00CC021B /* ClockLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03BF51C123A2978B008AD373 /* ClockLayer.swift */; };\n\t\t0396D53224B8B7ED00CC021B /* AerialVideo.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAC36F401BE1756D007F2A20 /* AerialVideo.swift */; };\n\t\t0396D53324B8B7ED00CC021B /* ErrorLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03893CB2217749F0008E7125 /* ErrorLog.swift */; };\n\t\t0396D53424B8B7ED00CC021B /* InfoSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0354D0EB23F6CB7B00D86F9E /* InfoSettingsView.swift */; };\n\t\t0396D53524B8B7ED00CC021B /* NSImage+trim.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03A4A80A2451CE2C00A1F7A3 /* NSImage+trim.swift */; };\n\t\t0396D53624B8B7ED00CC021B /* Battery.swift in Sources */ = {isa = PBXBuildFile; fileRef = 032D1160239A7D82007E7756 /* Battery.swift */; };\n\t\t0396D53724B8B7ED00CC021B /* VideoList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03C97BA624B5F74900739CED /* VideoList.swift */; };\n\t\t0396D53824B8B7ED00CC021B /* InfoBatteryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 038D2EE323B6565900CD91F7 /* InfoBatteryView.swift */; };\n\t\t0396D53A24B8B7ED00CC021B /* DateLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03FA49B62428F84500863AF6 /* DateLayer.swift */; };\n\t\t0396D53B24B8B7ED00CC021B /* AerialPlayerItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA7E2E5D1FC62E8B00E5F320 /* AerialPlayerItem.swift */; };\n\t\t0396D53C24B8B7ED00CC021B /* HardwareDetection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03608A2B22A56465008F08A2 /* HardwareDetection.swift */; };\n\t\t0396D53E24B8B7ED00CC021B /* YahooLogoLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03A42A9F2449F959003B3012 /* YahooLogoLayer.swift */; };\n\t\t0396D54024B8B7ED00CC021B /* InfoMessageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03A596D223AA750F0097EA66 /* InfoMessageView.swift */; };\n\t\t0396D54224B8B7ED00CC021B /* ConditionLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03A42AA2244A0E5F003B3012 /* ConditionLayer.swift */; };\n\t\t0396D54324B8B7ED00CC021B /* VideoManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03A2CB9B216BA9AF0061E8E8 /* VideoManager.swift */; };\n\t\t0396D54524B8B7ED00CC021B /* InfoContainerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 038C584623A9304800224630 /* InfoContainerView.swift */; };\n\t\t0396D54624B8B7ED00CC021B /* AerialView+Player.swift in Sources */ = {isa = PBXBuildFile; fileRef = 035D524E239AA31A00DC29DC /* AerialView+Player.swift */; };\n\t\t0396D54724B8B7ED00CC021B /* CustomVideoFolders+helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03AD45FE22981B0C00261325 /* CustomVideoFolders+helpers.swift */; };\n\t\t0396D54824B8B7ED00CC021B /* VideoLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAF450201BE2B45D00C1F98A /* VideoLoader.swift */; };\n\t\t0396D54924B8B7ED00CC021B /* TimeManagement.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E8731221675FE0002B469B /* TimeManagement.swift */; };\n\t\t0396D54A24B8B7ED00CC021B /* DownloadIndicatorLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 036A57D423F30DD00009DC02 /* DownloadIndicatorLayer.swift */; };\n\t\t0396D54B24B8B7ED00CC021B /* CountdownLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 036A57DA23F5820A0009DC02 /* CountdownLayer.swift */; };\n\t\t0396D54C24B8B7ED00CC021B /* SourceList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 034A6DC124ACC7C800D62129 /* SourceList.swift */; };\n\t\t0396D54D24B8B7ED00CC021B /* DescriptionCellView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03C344FE24B7A22300906EA6 /* DescriptionCellView.swift */; };\n\t\t0396D54E24B8B7ED00CC021B /* DisplayView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03D1E78622842FB300D10CF7 /* DisplayView.swift */; };\n\t\t0396D54F24B8B7ED00CC021B /* InfoLocationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03A596D823AB8F000097EA66 /* InfoLocationView.swift */; };\n\t\t0396D55024B8B7ED00CC021B /* AssetLoaderDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAB22A7D1BE17D7D0065C0F5 /* AssetLoaderDelegate.swift */; };\n\t\t0396D55124B8B7ED00CC021B /* PrefsVideos.swift in Sources */ = {isa = PBXBuildFile; fileRef = 038D2EDD23B0FB0D00CD91F7 /* PrefsVideos.swift */; };\n\t\t0396D55224B8B7ED00CC021B /* LocationLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0306336723A1012200046A59 /* LocationLayer.swift */; };\n\t\t0396D55424B8B7ED00CC021B /* InfoTableSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 034F29B623A7A93D004B34D5 /* InfoTableSource.swift */; };\n\t\t0396D55524B8B7ED00CC021B /* Solar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03958348217F4416008E8F9C /* Solar.swift */; };\n\t\t0396D55624B8B7ED00CC021B /* Brightness.swift in Sources */ = {isa = PBXBuildFile; fileRef = F008DAFC23AADCFB00739DE1 /* Brightness.swift */; };\n\t\t0396D55724B8B7ED00CC021B /* SourceInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03C97BC224B6210500739CED /* SourceInfo.swift */; };\n\t\t0396D55924B8B7ED00CC021B /* PrefsTime.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0361B9AA23D73D4500B6252D /* PrefsTime.swift */; };\n\t\t0396D55A24B8B7ED00CC021B /* PoiStringProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03233B67217272640077D3F9 /* PoiStringProvider.swift */; };\n\t\t0396D55B24B8B7ED00CC021B /* PrefsAdvanced.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03A4A80D2451D04C00A1F7A3 /* PrefsAdvanced.swift */; };\n\t\t0396D55C24B8B7ED00CC021B /* WeatherLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 033842E024489D7300A2C523 /* WeatherLayer.swift */; };\n\t\t0396D55D24B8B7ED00CC021B /* VideoDownload.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA36BD3E1BE57F8E00D5E03B /* VideoDownload.swift */; };\n\t\t0396D55E24B8B7ED00CC021B /* FileHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03C97BBF24B60E2F00739CED /* FileHelpers.swift */; };\n\t\t0396D55F24B8B7ED00CC021B /* InfoSettingsTableSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0354D0E823F6C31800D86F9E /* InfoSettingsTableSource.swift */; };\n\t\t0396D56024B8B7ED00CC021B /* DownloadManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E8730B2165013C002B469B /* DownloadManager.swift */; };\n\t\t0396D56224B8B7ED00CC021B /* InfoCountdownView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 036A57D723F470940009DC02 /* InfoCountdownView.swift */; };\n\t\t0396D56324B8B7ED00CC021B /* ConditionSymbolLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 033D68802453080C0016F837 /* ConditionSymbolLayer.swift */; };\n\t\t0396D56424B8B7ED00CC021B /* CheckboxCellView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03C344FB24B778EE00906EA6 /* CheckboxCellView.swift */; };\n\t\t0396D56524B8B7ED00CC021B /* AnimationLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 034587312449D8EB00C97D1B /* AnimationLayer.swift */; };\n\t\t0396D56624B8B7ED00CC021B /* AnimatableLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0345872C2449C52F00C97D1B /* AnimatableLayer.swift */; };\n\t\t0396D56724B8B7ED00CC021B /* InfoClockView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03A596D423AA752F0097EA66 /* InfoClockView.swift */; };\n\t\t0396D56824B8B7ED00CC021B /* CustomVideoController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0313F9E722942B4500B074BB /* CustomVideoController.swift */; };\n\t\t0396D56A24B8B7ED00CC021B /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 03510C722185EF76008F74F2 /* CoreLocation.framework */; };\n\t\t0396D56D24B8B7ED00CC021B /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 03510C6A21834EB2008F74F2 /* IOKit.framework */; };\n\t\t0396D56F24B8B7ED00CC021B /* Aerial-Bridging-Header.h in Headers */ = {isa = PBXBuildFile; fileRef = 03510C6D21834F38008F74F2 /* Aerial-Bridging-Header.h */; };\n\t\t0396D57624B8B7ED00CC021B /* white_retina.png in Resources */ = {isa = PBXBuildFile; fileRef = 03A42A822449F5EA003B3012 /* white_retina.png */; };\n\t\t0396D57924B8B7ED00CC021B /* screen2.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 03D1E78E22848F7F00D10CF7 /* screen2.jpg */; };\n\t\t0396D58B24B8B7ED00CC021B /* screen0.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 03D1E79022848F7F00D10CF7 /* screen0.jpg */; };\n\t\t0396D58D24B8B7ED00CC021B /* thumbnail@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 0395835121807D1F008E8F9C /* thumbnail@2x.png */; };\n\t\t0396D58E24B8B7ED00CC021B /* thumbnail.png in Resources */ = {isa = PBXBuildFile; fileRef = 0395835221807D1F008E8F9C /* thumbnail.png */; };\n\t\t0396D59224B8B7ED00CC021B /* screen1.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 03D1E78F22848F7F00D10CF7 /* screen1.jpg */; };\n\t\t0396D59D24B8B7ED00CC021B /* missingvideos.json in Resources */ = {isa = PBXBuildFile; fileRef = 0369985C2196103300E359D3 /* missingvideos.json */; };\n\t\t0396D5A824B8B7ED00CC021B /* CustomVideos.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0313F9E522942AA500B074BB /* CustomVideos.xib */; };\n\t\t0396D5AB24B8B7ED00CC021B /* purple_retina.png in Resources */ = {isa = PBXBuildFile; fileRef = 03A42A9B2449F601003B3012 /* purple_retina.png */; };\n\t\t03977EF1250E6918008FBAFD /* sv.json in Resources */ = {isa = PBXBuildFile; fileRef = 03977EE2250E6917008FBAFD /* sv.json */; };\n\t\t03977EF2250E6918008FBAFD /* sv.json in Resources */ = {isa = PBXBuildFile; fileRef = 03977EE2250E6917008FBAFD /* sv.json */; };\n\t\t03977EF3250E6918008FBAFD /* sv.json in Resources */ = {isa = PBXBuildFile; fileRef = 03977EE2250E6917008FBAFD /* sv.json */; };\n\t\t03977EF4250E6918008FBAFD /* ja.json in Resources */ = {isa = PBXBuildFile; fileRef = 03977EE3250E6917008FBAFD /* ja.json */; };\n\t\t03977EF5250E6918008FBAFD /* ja.json in Resources */ = {isa = PBXBuildFile; fileRef = 03977EE3250E6917008FBAFD /* ja.json */; };\n\t\t03977EF6250E6918008FBAFD /* ja.json in Resources */ = {isa = PBXBuildFile; fileRef = 03977EE3250E6917008FBAFD /* ja.json */; };\n\t\t03977EF7250E6918008FBAFD /* pt.json in Resources */ = {isa = PBXBuildFile; fileRef = 03977EE4250E6917008FBAFD /* pt.json */; };\n\t\t03977EF8250E6918008FBAFD /* pt.json in Resources */ = {isa = PBXBuildFile; fileRef = 03977EE4250E6917008FBAFD /* pt.json */; };\n\t\t03977EF9250E6918008FBAFD /* pt.json in Resources */ = {isa = PBXBuildFile; fileRef = 03977EE4250E6917008FBAFD /* pt.json */; };\n\t\t03977EFA250E6918008FBAFD /* zh_TW.json in Resources */ = {isa = PBXBuildFile; fileRef = 03977EE5250E6917008FBAFD /* zh_TW.json */; };\n\t\t03977EFB250E6918008FBAFD /* zh_TW.json in Resources */ = {isa = PBXBuildFile; fileRef = 03977EE5250E6917008FBAFD /* zh_TW.json */; };\n\t\t03977EFC250E6918008FBAFD /* zh_TW.json in Resources */ = {isa = PBXBuildFile; fileRef = 03977EE5250E6917008FBAFD /* zh_TW.json */; };\n\t\t03977EFD250E6918008FBAFD /* pl.json in Resources */ = {isa = PBXBuildFile; fileRef = 03977EE6250E6917008FBAFD /* pl.json */; };\n\t\t03977EFE250E6918008FBAFD /* pl.json in Resources */ = {isa = PBXBuildFile; fileRef = 03977EE6250E6917008FBAFD /* pl.json */; };\n\t\t03977EFF250E6918008FBAFD /* pl.json in Resources */ = {isa = PBXBuildFile; fileRef = 03977EE6250E6917008FBAFD /* pl.json */; };\n\t\t03977F00250E6918008FBAFD /* de.json in Resources */ = {isa = PBXBuildFile; fileRef = 03977EE7250E6918008FBAFD /* de.json */; };\n\t\t03977F01250E6918008FBAFD /* de.json in Resources */ = {isa = PBXBuildFile; fileRef = 03977EE7250E6918008FBAFD /* de.json */; };\n\t\t03977F02250E6918008FBAFD /* de.json in Resources */ = {isa = PBXBuildFile; fileRef = 03977EE7250E6918008FBAFD /* de.json */; };\n\t\t03977F03250E6918008FBAFD /* fr.json in Resources */ = {isa = PBXBuildFile; fileRef = 03977EE8250E6918008FBAFD /* fr.json */; };\n\t\t03977F04250E6918008FBAFD /* fr.json in Resources */ = {isa = PBXBuildFile; fileRef = 03977EE8250E6918008FBAFD /* fr.json */; };\n\t\t03977F05250E6918008FBAFD /* fr.json in Resources */ = {isa = PBXBuildFile; fileRef = 03977EE8250E6918008FBAFD /* fr.json */; };\n\t\t03977F06250E6918008FBAFD /* es.json in Resources */ = {isa = PBXBuildFile; fileRef = 03977EE9250E6918008FBAFD /* es.json */; };\n\t\t03977F07250E6918008FBAFD /* es.json in Resources */ = {isa = PBXBuildFile; fileRef = 03977EE9250E6918008FBAFD /* es.json */; };\n\t\t03977F08250E6918008FBAFD /* es.json in Resources */ = {isa = PBXBuildFile; fileRef = 03977EE9250E6918008FBAFD /* es.json */; };\n\t\t03977F09250E6918008FBAFD /* pt_BR.json in Resources */ = {isa = PBXBuildFile; fileRef = 03977EEA250E6918008FBAFD /* pt_BR.json */; };\n\t\t03977F0A250E6918008FBAFD /* pt_BR.json in Resources */ = {isa = PBXBuildFile; fileRef = 03977EEA250E6918008FBAFD /* pt_BR.json */; };\n\t\t03977F0B250E6918008FBAFD /* pt_BR.json in Resources */ = {isa = PBXBuildFile; fileRef = 03977EEA250E6918008FBAFD /* pt_BR.json */; };\n\t\t03977F0C250E6918008FBAFD /* it.json in Resources */ = {isa = PBXBuildFile; fileRef = 03977EEB250E6918008FBAFD /* it.json */; };\n\t\t03977F0D250E6918008FBAFD /* it.json in Resources */ = {isa = PBXBuildFile; fileRef = 03977EEB250E6918008FBAFD /* it.json */; };\n\t\t03977F0E250E6918008FBAFD /* it.json in Resources */ = {isa = PBXBuildFile; fileRef = 03977EEB250E6918008FBAFD /* it.json */; };\n\t\t03977F0F250E6918008FBAFD /* he.json in Resources */ = {isa = PBXBuildFile; fileRef = 03977EEC250E6918008FBAFD /* he.json */; };\n\t\t03977F10250E6918008FBAFD /* he.json in Resources */ = {isa = PBXBuildFile; fileRef = 03977EEC250E6918008FBAFD /* he.json */; };\n\t\t03977F11250E6918008FBAFD /* he.json in Resources */ = {isa = PBXBuildFile; fileRef = 03977EEC250E6918008FBAFD /* he.json */; };\n\t\t03977F12250E6918008FBAFD /* en.json in Resources */ = {isa = PBXBuildFile; fileRef = 03977EED250E6918008FBAFD /* en.json */; };\n\t\t03977F13250E6918008FBAFD /* en.json in Resources */ = {isa = PBXBuildFile; fileRef = 03977EED250E6918008FBAFD /* en.json */; };\n\t\t03977F14250E6918008FBAFD /* en.json in Resources */ = {isa = PBXBuildFile; fileRef = 03977EED250E6918008FBAFD /* en.json */; };\n\t\t03977F15250E6918008FBAFD /* zh_CN.json in Resources */ = {isa = PBXBuildFile; fileRef = 03977EEE250E6918008FBAFD /* zh_CN.json */; };\n\t\t03977F16250E6918008FBAFD /* zh_CN.json in Resources */ = {isa = PBXBuildFile; fileRef = 03977EEE250E6918008FBAFD /* zh_CN.json */; };\n\t\t03977F17250E6918008FBAFD /* zh_CN.json in Resources */ = {isa = PBXBuildFile; fileRef = 03977EEE250E6918008FBAFD /* zh_CN.json */; };\n\t\t03977F18250E6918008FBAFD /* ar.json in Resources */ = {isa = PBXBuildFile; fileRef = 03977EEF250E6918008FBAFD /* ar.json */; };\n\t\t03977F19250E6918008FBAFD /* ar.json in Resources */ = {isa = PBXBuildFile; fileRef = 03977EEF250E6918008FBAFD /* ar.json */; };\n\t\t03977F1A250E6918008FBAFD /* ar.json in Resources */ = {isa = PBXBuildFile; fileRef = 03977EEF250E6918008FBAFD /* ar.json */; };\n\t\t03977F1B250E6918008FBAFD /* nl.json in Resources */ = {isa = PBXBuildFile; fileRef = 03977EF0250E6918008FBAFD /* nl.json */; };\n\t\t03977F1C250E6918008FBAFD /* nl.json in Resources */ = {isa = PBXBuildFile; fileRef = 03977EF0250E6918008FBAFD /* nl.json */; };\n\t\t03977F1D250E6918008FBAFD /* nl.json in Resources */ = {isa = PBXBuildFile; fileRef = 03977EF0250E6918008FBAFD /* nl.json */; };\n\t\t03977F20250E7165008FBAFD /* TimeMachine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03977F1F250E7165008FBAFD /* TimeMachine.swift */; };\n\t\t03977F21250E7165008FBAFD /* TimeMachine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03977F1F250E7165008FBAFD /* TimeMachine.swift */; };\n\t\t03977F22250E7165008FBAFD /* TimeMachine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03977F1F250E7165008FBAFD /* TimeMachine.swift */; };\n\t\t03A2CB9C216BA9AF0061E8E8 /* VideoManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03A2CB9B216BA9AF0061E8E8 /* VideoManager.swift */; };\n\t\t03A2CB9D216BB1490061E8E8 /* VideoManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03A2CB9B216BA9AF0061E8E8 /* VideoManager.swift */; };\n\t\t03A42A992449F5EA003B3012 /* white_retina.png in Resources */ = {isa = PBXBuildFile; fileRef = 03A42A822449F5EA003B3012 /* white_retina.png */; };\n\t\t03A42A9A2449F5EA003B3012 /* white_retina.png in Resources */ = {isa = PBXBuildFile; fileRef = 03A42A822449F5EA003B3012 /* white_retina.png */; };\n\t\t03A42A9C2449F602003B3012 /* purple_retina.png in Resources */ = {isa = PBXBuildFile; fileRef = 03A42A9B2449F601003B3012 /* purple_retina.png */; };\n\t\t03A42A9D2449F602003B3012 /* purple_retina.png in Resources */ = {isa = PBXBuildFile; fileRef = 03A42A9B2449F601003B3012 /* purple_retina.png */; };\n\t\t03A42AA02449F959003B3012 /* YahooLogoLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03A42A9F2449F959003B3012 /* YahooLogoLayer.swift */; };\n\t\t03A42AA12449F959003B3012 /* YahooLogoLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03A42A9F2449F959003B3012 /* YahooLogoLayer.swift */; };\n\t\t03A42AA3244A0E5F003B3012 /* ConditionLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03A42AA2244A0E5F003B3012 /* ConditionLayer.swift */; };\n\t\t03A42AA4244A0E5F003B3012 /* ConditionLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03A42AA2244A0E5F003B3012 /* ConditionLayer.swift */; };\n\t\t03A4A80B2451CE2C00A1F7A3 /* NSImage+trim.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03A4A80A2451CE2C00A1F7A3 /* NSImage+trim.swift */; };\n\t\t03A4A80C2451CE2C00A1F7A3 /* NSImage+trim.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03A4A80A2451CE2C00A1F7A3 /* NSImage+trim.swift */; };\n\t\t03A4A80E2451D04C00A1F7A3 /* PrefsAdvanced.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03A4A80D2451D04C00A1F7A3 /* PrefsAdvanced.swift */; };\n\t\t03A4A80F2451D04C00A1F7A3 /* PrefsAdvanced.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03A4A80D2451D04C00A1F7A3 /* PrefsAdvanced.swift */; };\n\t\t03A596D323AA750F0097EA66 /* InfoMessageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03A596D223AA750F0097EA66 /* InfoMessageView.swift */; };\n\t\t03A596D523AA752F0097EA66 /* InfoClockView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03A596D423AA752F0097EA66 /* InfoClockView.swift */; };\n\t\t03A596D623AA752F0097EA66 /* InfoClockView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03A596D423AA752F0097EA66 /* InfoClockView.swift */; };\n\t\t03A596D723AA75490097EA66 /* InfoMessageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03A596D223AA750F0097EA66 /* InfoMessageView.swift */; };\n\t\t03A596D923AB8F000097EA66 /* InfoLocationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03A596D823AB8F000097EA66 /* InfoLocationView.swift */; };\n\t\t03A6D14625F109B900960135 /* OpenWeather.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03A6D14525F109B900960135 /* OpenWeather.swift */; };\n\t\t03A6D14725F109B900960135 /* OpenWeather.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03A6D14525F109B900960135 /* OpenWeather.swift */; };\n\t\t03A6D14825F109B900960135 /* OpenWeather.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03A6D14525F109B900960135 /* OpenWeather.swift */; };\n\t\t03A6D14F25F294C900960135 /* location.north.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03A6D14E25F294C900960135 /* location.north.pdf */; };\n\t\t03A6D15025F294C900960135 /* location.north.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03A6D14E25F294C900960135 /* location.north.pdf */; };\n\t\t03A6D15125F294C900960135 /* location.north.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03A6D14E25F294C900960135 /* location.north.pdf */; };\n\t\t03A6D15325F297CE00960135 /* WindDirectionLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03A6D15225F297CE00960135 /* WindDirectionLayer.swift */; };\n\t\t03A6D15425F297CE00960135 /* WindDirectionLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03A6D15225F297CE00960135 /* WindDirectionLayer.swift */; };\n\t\t03A6D15525F297CE00960135 /* WindDirectionLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03A6D15225F297CE00960135 /* WindDirectionLayer.swift */; };\n\t\t03AA27BD2614A6F800A4D2CF /* ko.json in Resources */ = {isa = PBXBuildFile; fileRef = 03AA27BC2614A6F800A4D2CF /* ko.json */; };\n\t\t03AA27BE2614A6F800A4D2CF /* ko.json in Resources */ = {isa = PBXBuildFile; fileRef = 03AA27BC2614A6F800A4D2CF /* ko.json */; };\n\t\t03AA27BF2614A6F800A4D2CF /* ko.json in Resources */ = {isa = PBXBuildFile; fileRef = 03AA27BC2614A6F800A4D2CF /* ko.json */; };\n\t\t03AA32622631A8F2002198C3 /* GeoCoding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03AA32612631A8F2002198C3 /* GeoCoding.swift */; };\n\t\t03AA32632631A8F2002198C3 /* GeoCoding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03AA32612631A8F2002198C3 /* GeoCoding.swift */; };\n\t\t03AA32642631A8F2002198C3 /* GeoCoding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03AA32612631A8F2002198C3 /* GeoCoding.swift */; };\n\t\t03AA7A5D24C84C6300A47970 /* cloud.bolt.rain.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A2524C84C6200A47970 /* cloud.bolt.rain.pdf */; };\n\t\t03AA7A5E24C84C6300A47970 /* cloud.bolt.rain.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A2524C84C6200A47970 /* cloud.bolt.rain.pdf */; };\n\t\t03AA7A5F24C84C6300A47970 /* cloud.bolt.rain.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A2524C84C6200A47970 /* cloud.bolt.rain.pdf */; };\n\t\t03AA7A6024C84C6300A47970 /* wind.snow.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A3C24C84C6200A47970 /* wind.snow.pdf */; };\n\t\t03AA7A6124C84C6300A47970 /* wind.snow.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A3C24C84C6200A47970 /* wind.snow.pdf */; };\n\t\t03AA7A6224C84C6300A47970 /* wind.snow.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A3C24C84C6200A47970 /* wind.snow.pdf */; };\n\t\t03AA7A6324C84C6300A47970 /* snow.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A3D24C84C6200A47970 /* snow.pdf */; };\n\t\t03AA7A6424C84C6300A47970 /* snow.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A3D24C84C6200A47970 /* snow.pdf */; };\n\t\t03AA7A6524C84C6300A47970 /* snow.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A3D24C84C6200A47970 /* snow.pdf */; };\n\t\t03AA7A6624C84C6300A47970 /* moon.stars.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A3E24C84C6200A47970 /* moon.stars.pdf */; };\n\t\t03AA7A6724C84C6300A47970 /* moon.stars.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A3E24C84C6200A47970 /* moon.stars.pdf */; };\n\t\t03AA7A6824C84C6300A47970 /* moon.stars.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A3E24C84C6200A47970 /* moon.stars.pdf */; };\n\t\t03AA7A6924C84C6300A47970 /* cloud.heavyrain.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A3F24C84C6200A47970 /* cloud.heavyrain.pdf */; };\n\t\t03AA7A6A24C84C6300A47970 /* cloud.heavyrain.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A3F24C84C6200A47970 /* cloud.heavyrain.pdf */; };\n\t\t03AA7A6B24C84C6300A47970 /* cloud.heavyrain.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A3F24C84C6200A47970 /* cloud.heavyrain.pdf */; };\n\t\t03AA7A6C24C84C6300A47970 /* battery.0.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A4024C84C6200A47970 /* battery.0.pdf */; };\n\t\t03AA7A6D24C84C6300A47970 /* battery.0.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A4024C84C6200A47970 /* battery.0.pdf */; };\n\t\t03AA7A6E24C84C6300A47970 /* battery.0.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A4024C84C6200A47970 /* battery.0.pdf */; };\n\t\t03AA7A6F24C84C6300A47970 /* wrench.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A4124C84C6200A47970 /* wrench.pdf */; };\n\t\t03AA7A7024C84C6300A47970 /* wrench.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A4124C84C6200A47970 /* wrench.pdf */; };\n\t\t03AA7A7124C84C6300A47970 /* wrench.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A4124C84C6200A47970 /* wrench.pdf */; };\n\t\t03AA7A7224C84C6300A47970 /* cloud.sun.rain.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A4224C84C6200A47970 /* cloud.sun.rain.pdf */; };\n\t\t03AA7A7324C84C6300A47970 /* cloud.sun.rain.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A4224C84C6200A47970 /* cloud.sun.rain.pdf */; };\n\t\t03AA7A7424C84C6300A47970 /* cloud.sun.rain.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A4224C84C6200A47970 /* cloud.sun.rain.pdf */; };\n\t\t03AA7A7524C84C6300A47970 /* sun.dust.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A4324C84C6200A47970 /* sun.dust.pdf */; };\n\t\t03AA7A7624C84C6300A47970 /* sun.dust.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A4324C84C6200A47970 /* sun.dust.pdf */; };\n\t\t03AA7A7724C84C6300A47970 /* sun.dust.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A4324C84C6200A47970 /* sun.dust.pdf */; };\n\t\t03AA7A7824C84C6300A47970 /* sun.max.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A4424C84C6200A47970 /* sun.max.pdf */; };\n\t\t03AA7A7924C84C6300A47970 /* sun.max.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A4424C84C6200A47970 /* sun.max.pdf */; };\n\t\t03AA7A7A24C84C6300A47970 /* sun.max.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A4424C84C6200A47970 /* sun.max.pdf */; };\n\t\t03AA7A7B24C84C6300A47970 /* cloud.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A4524C84C6200A47970 /* cloud.pdf */; };\n\t\t03AA7A7C24C84C6300A47970 /* cloud.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A4524C84C6200A47970 /* cloud.pdf */; };\n\t\t03AA7A7D24C84C6300A47970 /* cloud.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A4524C84C6200A47970 /* cloud.pdf */; };\n\t\t03AA7A7E24C84C6300A47970 /* cloud.sun.bolt.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A4624C84C6200A47970 /* cloud.sun.bolt.pdf */; };\n\t\t03AA7A7F24C84C6300A47970 /* cloud.sun.bolt.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A4624C84C6200A47970 /* cloud.sun.bolt.pdf */; };\n\t\t03AA7A8024C84C6300A47970 /* cloud.sun.bolt.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A4624C84C6200A47970 /* cloud.sun.bolt.pdf */; };\n\t\t03AA7A8124C84C6300A47970 /* thermometer.snowflake.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A4724C84C6200A47970 /* thermometer.snowflake.pdf */; };\n\t\t03AA7A8224C84C6300A47970 /* thermometer.snowflake.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A4724C84C6200A47970 /* thermometer.snowflake.pdf */; };\n\t\t03AA7A8324C84C6300A47970 /* thermometer.snowflake.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A4724C84C6200A47970 /* thermometer.snowflake.pdf */; };\n\t\t03AA7A8424C84C6300A47970 /* hurricane.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A4824C84C6200A47970 /* hurricane.pdf */; };\n\t\t03AA7A8524C84C6300A47970 /* hurricane.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A4824C84C6200A47970 /* hurricane.pdf */; };\n\t\t03AA7A8624C84C6300A47970 /* hurricane.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A4824C84C6200A47970 /* hurricane.pdf */; };\n\t\t03AA7A8724C84C6300A47970 /* cloud.fog.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A4924C84C6200A47970 /* cloud.fog.pdf */; };\n\t\t03AA7A8824C84C6300A47970 /* cloud.fog.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A4924C84C6200A47970 /* cloud.fog.pdf */; };\n\t\t03AA7A8924C84C6300A47970 /* cloud.fog.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A4924C84C6200A47970 /* cloud.fog.pdf */; };\n\t\t03AA7A8A24C84C6300A47970 /* thermometer.sun.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A4A24C84C6200A47970 /* thermometer.sun.pdf */; };\n\t\t03AA7A8B24C84C6300A47970 /* thermometer.sun.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A4A24C84C6200A47970 /* thermometer.sun.pdf */; };\n\t\t03AA7A8C24C84C6300A47970 /* thermometer.sun.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A4A24C84C6200A47970 /* thermometer.sun.pdf */; };\n\t\t03AA7A8D24C84C6300A47970 /* tropicalstorm.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A4B24C84C6200A47970 /* tropicalstorm.pdf */; };\n\t\t03AA7A8E24C84C6300A47970 /* tropicalstorm.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A4B24C84C6200A47970 /* tropicalstorm.pdf */; };\n\t\t03AA7A8F24C84C6300A47970 /* tropicalstorm.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A4B24C84C6200A47970 /* tropicalstorm.pdf */; };\n\t\t03AA7A9024C84C6300A47970 /* moon.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A4C24C84C6300A47970 /* moon.pdf */; };\n\t\t03AA7A9124C84C6300A47970 /* moon.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A4C24C84C6300A47970 /* moon.pdf */; };\n\t\t03AA7A9224C84C6300A47970 /* moon.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A4C24C84C6300A47970 /* moon.pdf */; };\n\t\t03AA7A9324C84C6300A47970 /* sun.min.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A4D24C84C6300A47970 /* sun.min.pdf */; };\n\t\t03AA7A9424C84C6300A47970 /* sun.min.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A4D24C84C6300A47970 /* sun.min.pdf */; };\n\t\t03AA7A9524C84C6300A47970 /* sun.min.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A4D24C84C6300A47970 /* sun.min.pdf */; };\n\t\t03AA7A9624C84C6300A47970 /* smoke.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A4E24C84C6300A47970 /* smoke.pdf */; };\n\t\t03AA7A9724C84C6300A47970 /* smoke.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A4E24C84C6300A47970 /* smoke.pdf */; };\n\t\t03AA7A9824C84C6300A47970 /* smoke.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A4E24C84C6300A47970 /* smoke.pdf */; };\n\t\t03AA7A9924C84C6300A47970 /* cloud.snow.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A4F24C84C6300A47970 /* cloud.snow.pdf */; };\n\t\t03AA7A9A24C84C6300A47970 /* cloud.snow.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A4F24C84C6300A47970 /* cloud.snow.pdf */; };\n\t\t03AA7A9B24C84C6300A47970 /* cloud.snow.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A4F24C84C6300A47970 /* cloud.snow.pdf */; };\n\t\t03AA7A9C24C84C6300A47970 /* cloud.moon.rain.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A5024C84C6300A47970 /* cloud.moon.rain.pdf */; };\n\t\t03AA7A9D24C84C6300A47970 /* cloud.moon.rain.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A5024C84C6300A47970 /* cloud.moon.rain.pdf */; };\n\t\t03AA7A9E24C84C6300A47970 /* cloud.moon.rain.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A5024C84C6300A47970 /* cloud.moon.rain.pdf */; };\n\t\t03AA7A9F24C84C6300A47970 /* cloud.hail.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A5124C84C6300A47970 /* cloud.hail.pdf */; };\n\t\t03AA7AA024C84C6300A47970 /* cloud.hail.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A5124C84C6300A47970 /* cloud.hail.pdf */; };\n\t\t03AA7AA124C84C6300A47970 /* cloud.hail.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A5124C84C6300A47970 /* cloud.hail.pdf */; };\n\t\t03AA7AA224C84C6300A47970 /* cloud.drizzle.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A5224C84C6300A47970 /* cloud.drizzle.pdf */; };\n\t\t03AA7AA324C84C6300A47970 /* cloud.drizzle.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A5224C84C6300A47970 /* cloud.drizzle.pdf */; };\n\t\t03AA7AA424C84C6300A47970 /* cloud.drizzle.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A5224C84C6300A47970 /* cloud.drizzle.pdf */; };\n\t\t03AA7AA524C84C6300A47970 /* cloud.rain.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A5324C84C6300A47970 /* cloud.rain.pdf */; };\n\t\t03AA7AA624C84C6300A47970 /* cloud.rain.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A5324C84C6300A47970 /* cloud.rain.pdf */; };\n\t\t03AA7AA724C84C6300A47970 /* cloud.rain.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A5324C84C6300A47970 /* cloud.rain.pdf */; };\n\t\t03AA7AA824C84C6300A47970 /* sun.haze.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A5424C84C6300A47970 /* sun.haze.pdf */; };\n\t\t03AA7AA924C84C6300A47970 /* sun.haze.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A5424C84C6300A47970 /* sun.haze.pdf */; };\n\t\t03AA7AAA24C84C6300A47970 /* sun.haze.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A5424C84C6300A47970 /* sun.haze.pdf */; };\n\t\t03AA7AAB24C84C6300A47970 /* tornado.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A5524C84C6300A47970 /* tornado.pdf */; };\n\t\t03AA7AAC24C84C6300A47970 /* tornado.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A5524C84C6300A47970 /* tornado.pdf */; };\n\t\t03AA7AAD24C84C6300A47970 /* tornado.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A5524C84C6300A47970 /* tornado.pdf */; };\n\t\t03AA7AAE24C84C6300A47970 /* cloud.moon.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A5624C84C6300A47970 /* cloud.moon.pdf */; };\n\t\t03AA7AAF24C84C6400A47970 /* cloud.moon.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A5624C84C6300A47970 /* cloud.moon.pdf */; };\n\t\t03AA7AB024C84C6400A47970 /* cloud.moon.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A5624C84C6300A47970 /* cloud.moon.pdf */; };\n\t\t03AA7AB124C84C6400A47970 /* cloud.moon.bolt.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A5724C84C6300A47970 /* cloud.moon.bolt.pdf */; };\n\t\t03AA7AB224C84C6400A47970 /* cloud.moon.bolt.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A5724C84C6300A47970 /* cloud.moon.bolt.pdf */; };\n\t\t03AA7AB324C84C6400A47970 /* cloud.moon.bolt.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A5724C84C6300A47970 /* cloud.moon.bolt.pdf */; };\n\t\t03AA7AB424C84C6400A47970 /* cloud.bolt.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A5824C84C6300A47970 /* cloud.bolt.pdf */; };\n\t\t03AA7AB524C84C6400A47970 /* cloud.bolt.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A5824C84C6300A47970 /* cloud.bolt.pdf */; };\n\t\t03AA7AB624C84C6400A47970 /* cloud.bolt.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A5824C84C6300A47970 /* cloud.bolt.pdf */; };\n\t\t03AA7AB724C84C6400A47970 /* bolt.fill.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A5924C84C6300A47970 /* bolt.fill.pdf */; };\n\t\t03AA7AB824C84C6400A47970 /* bolt.fill.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A5924C84C6300A47970 /* bolt.fill.pdf */; };\n\t\t03AA7AB924C84C6400A47970 /* bolt.fill.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A5924C84C6300A47970 /* bolt.fill.pdf */; };\n\t\t03AA7ABA24C84C6400A47970 /* cloud.sun.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A5A24C84C6300A47970 /* cloud.sun.pdf */; };\n\t\t03AA7ABB24C84C6400A47970 /* cloud.sun.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A5A24C84C6300A47970 /* cloud.sun.pdf */; };\n\t\t03AA7ABC24C84C6400A47970 /* cloud.sun.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A5A24C84C6300A47970 /* cloud.sun.pdf */; };\n\t\t03AA7ABD24C84C6400A47970 /* cloud.sleet.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A5B24C84C6300A47970 /* cloud.sleet.pdf */; };\n\t\t03AA7ABE24C84C6400A47970 /* cloud.sleet.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A5B24C84C6300A47970 /* cloud.sleet.pdf */; };\n\t\t03AA7ABF24C84C6400A47970 /* cloud.sleet.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A5B24C84C6300A47970 /* cloud.sleet.pdf */; };\n\t\t03AA7AC024C84C6400A47970 /* wind.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A5C24C84C6300A47970 /* wind.pdf */; };\n\t\t03AA7AC124C84C6400A47970 /* wind.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A5C24C84C6300A47970 /* wind.pdf */; };\n\t\t03AA7AC224C84C6400A47970 /* wind.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03AA7A5C24C84C6300A47970 /* wind.pdf */; };\n\t\t03AD45FF22981B0C00261325 /* CustomVideoFolders+helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03AD45FE22981B0C00261325 /* CustomVideoFolders+helpers.swift */; };\n\t\t03AD460022981B1C00261325 /* CustomVideoFolders+helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03AD45FE22981B0C00261325 /* CustomVideoFolders+helpers.swift */; };\n\t\t03B8742224E41CF8008E3D1B /* CacheSetupViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03B8742024E41CF8008E3D1B /* CacheSetupViewController.swift */; };\n\t\t03B8742324E41CF8008E3D1B /* CacheSetupViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03B8742024E41CF8008E3D1B /* CacheSetupViewController.swift */; };\n\t\t03B8742424E41CF8008E3D1B /* CacheSetupViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03B8742024E41CF8008E3D1B /* CacheSetupViewController.swift */; };\n\t\t03B8742524E41CF8008E3D1B /* CacheSetupViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 03B8742124E41CF8008E3D1B /* CacheSetupViewController.xib */; };\n\t\t03B8742624E41CF8008E3D1B /* CacheSetupViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 03B8742124E41CF8008E3D1B /* CacheSetupViewController.xib */; };\n\t\t03B8742724E41CF8008E3D1B /* CacheSetupViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 03B8742124E41CF8008E3D1B /* CacheSetupViewController.xib */; };\n\t\t03B8743224E42675008E3D1B /* wand.and.rays.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03B8742F24E42675008E3D1B /* wand.and.rays.pdf */; };\n\t\t03B8743324E42675008E3D1B /* wand.and.rays.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03B8742F24E42675008E3D1B /* wand.and.rays.pdf */; };\n\t\t03B8743424E42675008E3D1B /* wand.and.rays.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03B8742F24E42675008E3D1B /* wand.and.rays.pdf */; };\n\t\t03B8743524E42675008E3D1B /* wand.and.stars.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03B8743024E42675008E3D1B /* wand.and.stars.pdf */; };\n\t\t03B8743624E42675008E3D1B /* wand.and.stars.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03B8743024E42675008E3D1B /* wand.and.stars.pdf */; };\n\t\t03B8743724E42675008E3D1B /* wand.and.stars.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03B8743024E42675008E3D1B /* wand.and.stars.pdf */; };\n\t\t03B8743824E42675008E3D1B /* hand.raised.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03B8743124E42675008E3D1B /* hand.raised.pdf */; };\n\t\t03B8743924E42675008E3D1B /* hand.raised.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03B8743124E42675008E3D1B /* hand.raised.pdf */; };\n\t\t03B8743A24E42675008E3D1B /* hand.raised.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03B8743124E42675008E3D1B /* hand.raised.pdf */; };\n\t\t03BDBEA224C467EC00BBD5E9 /* BrightnessViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03BDBEA024C467EC00BBD5E9 /* BrightnessViewController.swift */; };\n\t\t03BDBEA324C467EC00BBD5E9 /* BrightnessViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03BDBEA024C467EC00BBD5E9 /* BrightnessViewController.swift */; };\n\t\t03BDBEA424C467EC00BBD5E9 /* BrightnessViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03BDBEA024C467EC00BBD5E9 /* BrightnessViewController.swift */; };\n\t\t03BDBEA524C467EC00BBD5E9 /* BrightnessViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 03BDBEA124C467EC00BBD5E9 /* BrightnessViewController.xib */; };\n\t\t03BDBEA624C467EC00BBD5E9 /* BrightnessViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 03BDBEA124C467EC00BBD5E9 /* BrightnessViewController.xib */; };\n\t\t03BDBEA724C467EC00BBD5E9 /* BrightnessViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 03BDBEA124C467EC00BBD5E9 /* BrightnessViewController.xib */; };\n\t\t03BDBEC024C4727C00BBD5E9 /* TimeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03BDBEBE24C4727C00BBD5E9 /* TimeViewController.swift */; };\n\t\t03BDBEC124C4727C00BBD5E9 /* TimeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03BDBEBE24C4727C00BBD5E9 /* TimeViewController.swift */; };\n\t\t03BDBEC224C4727C00BBD5E9 /* TimeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03BDBEBE24C4727C00BBD5E9 /* TimeViewController.swift */; };\n\t\t03BDBEC324C4727C00BBD5E9 /* TimeViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 03BDBEBF24C4727C00BBD5E9 /* TimeViewController.xib */; };\n\t\t03BDBEC424C4727C00BBD5E9 /* TimeViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 03BDBEBF24C4727C00BBD5E9 /* TimeViewController.xib */; };\n\t\t03BDBEC524C4727C00BBD5E9 /* TimeViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 03BDBEBF24C4727C00BBD5E9 /* TimeViewController.xib */; };\n\t\t03BF179F24E2F29C0080EF34 /* VideoFormatViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03BF179D24E2F29C0080EF34 /* VideoFormatViewController.swift */; };\n\t\t03BF17A024E2F29C0080EF34 /* VideoFormatViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03BF179D24E2F29C0080EF34 /* VideoFormatViewController.swift */; };\n\t\t03BF17A124E2F29C0080EF34 /* VideoFormatViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03BF179D24E2F29C0080EF34 /* VideoFormatViewController.swift */; };\n\t\t03BF17A224E2F29C0080EF34 /* VideoFormatViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 03BF179E24E2F29C0080EF34 /* VideoFormatViewController.xib */; };\n\t\t03BF17A324E2F29C0080EF34 /* VideoFormatViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 03BF179E24E2F29C0080EF34 /* VideoFormatViewController.xib */; };\n\t\t03BF17A424E2F29C0080EF34 /* VideoFormatViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 03BF179E24E2F29C0080EF34 /* VideoFormatViewController.xib */; };\n\t\t03BF51BA23A24B40008AD373 /* AnimationTextLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0306336D23A15FA900046A59 /* AnimationTextLayer.swift */; };\n\t\t03BF51BC23A2643C008AD373 /* LayerManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03BF51BB23A2643C008AD373 /* LayerManager.swift */; };\n\t\t03BF51BD23A26522008AD373 /* LayerManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03BF51BB23A2643C008AD373 /* LayerManager.swift */; };\n\t\t03BF51BF23A274CA008AD373 /* MessageLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03BF51BE23A274CA008AD373 /* MessageLayer.swift */; };\n\t\t03BF51C023A275D9008AD373 /* MessageLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03BF51BE23A274CA008AD373 /* MessageLayer.swift */; };\n\t\t03BF51C223A2978B008AD373 /* ClockLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03BF51C123A2978B008AD373 /* ClockLayer.swift */; };\n\t\t03BF51C323A29E1D008AD373 /* ClockLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03BF51C123A2978B008AD373 /* ClockLayer.swift */; };\n\t\t03C344FC24B778EE00906EA6 /* CheckboxCellView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03C344FB24B778EE00906EA6 /* CheckboxCellView.swift */; };\n\t\t03C344FD24B778EE00906EA6 /* CheckboxCellView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03C344FB24B778EE00906EA6 /* CheckboxCellView.swift */; };\n\t\t03C344FF24B7A22300906EA6 /* DescriptionCellView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03C344FE24B7A22300906EA6 /* DescriptionCellView.swift */; };\n\t\t03C3450024B7A22300906EA6 /* DescriptionCellView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03C344FE24B7A22300906EA6 /* DescriptionCellView.swift */; };\n\t\t03C605DC277B45CA005CA51F /* DispatchQueue+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03C605DB277B45CA005CA51F /* DispatchQueue+Extension.swift */; };\n\t\t03C605DD277B45CA005CA51F /* DispatchQueue+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03C605DB277B45CA005CA51F /* DispatchQueue+Extension.swift */; };\n\t\t03C605DE277B45CA005CA51F /* DispatchQueue+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03C605DB277B45CA005CA51F /* DispatchQueue+Extension.swift */; };\n\t\t03C97BA724B5F74900739CED /* VideoList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03C97BA624B5F74900739CED /* VideoList.swift */; };\n\t\t03C97BA824B5F74900739CED /* VideoList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03C97BA624B5F74900739CED /* VideoList.swift */; };\n\t\t03C97BC024B60E2F00739CED /* FileHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03C97BBF24B60E2F00739CED /* FileHelpers.swift */; };\n\t\t03C97BC124B60E2F00739CED /* FileHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03C97BBF24B60E2F00739CED /* FileHelpers.swift */; };\n\t\t03C97BC324B6210500739CED /* SourceInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03C97BC224B6210500739CED /* SourceInfo.swift */; };\n\t\t03C97BC424B6210500739CED /* SourceInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03C97BC224B6210500739CED /* SourceInfo.swift */; };\n\t\t03D1E78722842FB300D10CF7 /* DisplayView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03D1E78622842FB300D10CF7 /* DisplayView.swift */; };\n\t\t03D1E7882284367200D10CF7 /* DisplayView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03D1E78622842FB300D10CF7 /* DisplayView.swift */; };\n\t\t03D1E78A2284471A00D10CF7 /* DisplayDetection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03D1E7892284471A00D10CF7 /* DisplayDetection.swift */; };\n\t\t03D1E78B22844AFD00D10CF7 /* DisplayDetection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03D1E7892284471A00D10CF7 /* DisplayDetection.swift */; };\n\t\t03D1E79122848F7F00D10CF7 /* screen2.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 03D1E78E22848F7F00D10CF7 /* screen2.jpg */; };\n\t\t03D1E79222848F7F00D10CF7 /* screen2.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 03D1E78E22848F7F00D10CF7 /* screen2.jpg */; };\n\t\t03D1E79322848F7F00D10CF7 /* screen2.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 03D1E78E22848F7F00D10CF7 /* screen2.jpg */; };\n\t\t03D1E79422848F7F00D10CF7 /* screen1.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 03D1E78F22848F7F00D10CF7 /* screen1.jpg */; };\n\t\t03D1E79522848F7F00D10CF7 /* screen1.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 03D1E78F22848F7F00D10CF7 /* screen1.jpg */; };\n\t\t03D1E79622848F7F00D10CF7 /* screen1.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 03D1E78F22848F7F00D10CF7 /* screen1.jpg */; };\n\t\t03D1E79722848F7F00D10CF7 /* screen0.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 03D1E79022848F7F00D10CF7 /* screen0.jpg */; };\n\t\t03D1E79822848F7F00D10CF7 /* screen0.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 03D1E79022848F7F00D10CF7 /* screen0.jpg */; };\n\t\t03D1E79922848F7F00D10CF7 /* screen0.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 03D1E79022848F7F00D10CF7 /* screen0.jpg */; };\n\t\t03D3A10D24C5D7CC0091FE99 /* Thumbnails.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03D3A10C24C5D7CC0091FE99 /* Thumbnails.swift */; };\n\t\t03D3A10E24C5D7CC0091FE99 /* Thumbnails.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03D3A10C24C5D7CC0091FE99 /* Thumbnails.swift */; };\n\t\t03D3A10F24C5D7CC0091FE99 /* Thumbnails.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03D3A10C24C5D7CC0091FE99 /* Thumbnails.swift */; };\n\t\t03D3A11324C5FC770091FE99 /* AspectFillNSImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03D3A11224C5FC770091FE99 /* AspectFillNSImageView.swift */; };\n\t\t03D3A11424C5FC770091FE99 /* AspectFillNSImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03D3A11224C5FC770091FE99 /* AspectFillNSImageView.swift */; };\n\t\t03D3A11524C5FC770091FE99 /* AspectFillNSImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03D3A11224C5FC770091FE99 /* AspectFillNSImageView.swift */; };\n\t\t03DAD470229EAC66000DA6D1 /* Installation.md in Resources */ = {isa = PBXBuildFile; fileRef = 03DAD46F229EAC66000DA6D1 /* Installation.md */; };\n\t\t03DAD473229EC031000DA6D1 /* Readme.md in Resources */ = {isa = PBXBuildFile; fileRef = 03DAD472229EC031000DA6D1 /* Readme.md */; };\n\t\t03DB9674256569F800BFCF20 /* icon-512@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 03DB966D256569F800BFCF20 /* icon-512@2x.png */; };\n\t\t03DB9675256569F800BFCF20 /* icon-512@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 03DB966D256569F800BFCF20 /* icon-512@2x.png */; };\n\t\t03DB9676256569F800BFCF20 /* icon-512@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 03DB966D256569F800BFCF20 /* icon-512@2x.png */; };\n\t\t03DB968425657AE600BFCF20 /* LogoIcon-128px@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 03DB968325657AE600BFCF20 /* LogoIcon-128px@2x.png */; };\n\t\t03DB968525657AE600BFCF20 /* LogoIcon-128px@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 03DB968325657AE600BFCF20 /* LogoIcon-128px@2x.png */; };\n\t\t03DB968625657AE600BFCF20 /* LogoIcon-128px@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 03DB968325657AE600BFCF20 /* LogoIcon-128px@2x.png */; };\n\t\t03DC004E248BC5A4005DB0F4 /* Cache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03DC004D248BC5A4005DB0F4 /* Cache.swift */; };\n\t\t03DC0065248BC60D005DB0F4 /* Cache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03DC004D248BC5A4005DB0F4 /* Cache.swift */; };\n\t\t03E168162673A23900D7442D /* InfoMusicView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E168152673A23900D7442D /* InfoMusicView.swift */; };\n\t\t03E168172673A23900D7442D /* InfoMusicView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E168152673A23900D7442D /* InfoMusicView.swift */; };\n\t\t03E168182673A23900D7442D /* InfoMusicView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E168152673A23900D7442D /* InfoMusicView.swift */; };\n\t\t03E1681A2673A63F00D7442D /* MusicLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E168192673A63F00D7442D /* MusicLayer.swift */; };\n\t\t03E1681B2673A63F00D7442D /* MusicLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E168192673A63F00D7442D /* MusicLayer.swift */; };\n\t\t03E1681C2673A63F00D7442D /* MusicLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E168192673A63F00D7442D /* MusicLayer.swift */; };\n\t\t03E2237124BE048900CD8ED4 /* VideoHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E2237024BE048900CD8ED4 /* VideoHeaderView.swift */; };\n\t\t03E2237224BE048900CD8ED4 /* VideoHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E2237024BE048900CD8ED4 /* VideoHeaderView.swift */; };\n\t\t03E2237324BE048900CD8ED4 /* VideoHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E2237024BE048900CD8ED4 /* VideoHeaderView.swift */; };\n\t\t03E3C1DE256AAAF6000A2A5B /* ru.json in Resources */ = {isa = PBXBuildFile; fileRef = 03E3C1D7256AAAF6000A2A5B /* ru.json */; };\n\t\t03E3C1DF256AAAF6000A2A5B /* ru.json in Resources */ = {isa = PBXBuildFile; fileRef = 03E3C1D7256AAAF6000A2A5B /* ru.json */; };\n\t\t03E3C1E0256AAAF6000A2A5B /* ru.json in Resources */ = {isa = PBXBuildFile; fileRef = 03E3C1D7256AAAF6000A2A5B /* ru.json */; };\n\t\t03E8730C2165013C002B469B /* DownloadManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E8730B2165013C002B469B /* DownloadManager.swift */; };\n\t\t03E8730F216501ED002B469B /* AsynchronousOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E8730E216501ED002B469B /* AsynchronousOperation.swift */; };\n\t\t03E8731021662AEB002B469B /* DownloadManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E8730B2165013C002B469B /* DownloadManager.swift */; };\n\t\t03E8731121662AEB002B469B /* AsynchronousOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E8730E216501ED002B469B /* AsynchronousOperation.swift */; };\n\t\t03E8731321675FE0002B469B /* TimeManagement.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E8731221675FE0002B469B /* TimeManagement.swift */; };\n\t\t03E87314216760B7002B469B /* TimeManagement.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E8731221675FE0002B469B /* TimeManagement.swift */; };\n\t\t03EBF0C02746A53B00EC09D1 /* PlayingCollectionViewItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03EBF0BE2746A53B00EC09D1 /* PlayingCollectionViewItem.swift */; };\n\t\t03EBF0C12746A53B00EC09D1 /* PlayingCollectionViewItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03EBF0BE2746A53B00EC09D1 /* PlayingCollectionViewItem.swift */; };\n\t\t03EBF0C22746A53B00EC09D1 /* PlayingCollectionViewItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03EBF0BE2746A53B00EC09D1 /* PlayingCollectionViewItem.swift */; };\n\t\t03EBF0C32746A53B00EC09D1 /* PlayingCollectionViewItem.xib in Resources */ = {isa = PBXBuildFile; fileRef = 03EBF0BF2746A53B00EC09D1 /* PlayingCollectionViewItem.xib */; };\n\t\t03EBF0C42746A53B00EC09D1 /* PlayingCollectionViewItem.xib in Resources */ = {isa = PBXBuildFile; fileRef = 03EBF0BF2746A53B00EC09D1 /* PlayingCollectionViewItem.xib */; };\n\t\t03EBF0C52746A53B00EC09D1 /* PlayingCollectionViewItem.xib in Resources */ = {isa = PBXBuildFile; fileRef = 03EBF0BF2746A53B00EC09D1 /* PlayingCollectionViewItem.xib */; };\n\t\t03EED2F024C44A7900F0C3D4 /* OverlaysViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03EED2EE24C44A7900F0C3D4 /* OverlaysViewController.swift */; };\n\t\t03EED2F124C44A7900F0C3D4 /* OverlaysViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03EED2EE24C44A7900F0C3D4 /* OverlaysViewController.swift */; };\n\t\t03EED2F224C44A7900F0C3D4 /* OverlaysViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03EED2EE24C44A7900F0C3D4 /* OverlaysViewController.swift */; };\n\t\t03EED2F324C44A7900F0C3D4 /* OverlaysViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 03EED2EF24C44A7900F0C3D4 /* OverlaysViewController.xib */; };\n\t\t03EED2F424C44A7900F0C3D4 /* OverlaysViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 03EED2EF24C44A7900F0C3D4 /* OverlaysViewController.xib */; };\n\t\t03EED2F524C44A7900F0C3D4 /* OverlaysViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 03EED2EF24C44A7900F0C3D4 /* OverlaysViewController.xib */; };\n\t\t03F3C1BA24F2A923007733B5 /* kofi1@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 03F3C1B924F2A923007733B5 /* kofi1@2x.png */; };\n\t\t03F3C1BB24F2A923007733B5 /* kofi1@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 03F3C1B924F2A923007733B5 /* kofi1@2x.png */; };\n\t\t03F3C1BC24F2A923007733B5 /* kofi1@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 03F3C1B924F2A923007733B5 /* kofi1@2x.png */; };\n\t\t03F5551B24E9C091003AAD0B /* SourceOutlineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03F5551A24E9C091003AAD0B /* SourceOutlineView.swift */; };\n\t\t03F5551C24E9C091003AAD0B /* SourceOutlineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03F5551A24E9C091003AAD0B /* SourceOutlineView.swift */; };\n\t\t03F5551D24E9C091003AAD0B /* SourceOutlineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03F5551A24E9C091003AAD0B /* SourceOutlineView.swift */; };\n\t\t03F752D324EED19C00945B1D /* video_inspire_alabama_montgomery_countryside_00007.png in Resources */ = {isa = PBXBuildFile; fileRef = 03F752CF24EED19B00945B1D /* video_inspire_alabama_montgomery_countryside_00007.png */; };\n\t\t03F752D424EED19C00945B1D /* video_inspire_alabama_montgomery_countryside_00007.png in Resources */ = {isa = PBXBuildFile; fileRef = 03F752CF24EED19B00945B1D /* video_inspire_alabama_montgomery_countryside_00007.png */; };\n\t\t03F752D524EED19C00945B1D /* video_inspire_alabama_montgomery_countryside_00007.png in Resources */ = {isa = PBXBuildFile; fileRef = 03F752CF24EED19B00945B1D /* video_inspire_alabama_montgomery_countryside_00007.png */; };\n\t\t03F752D624EED19C00945B1D /* video_inspire_alabama_montgomery_countryside_00007.png in Resources */ = {isa = PBXBuildFile; fileRef = 03F752CF24EED19B00945B1D /* video_inspire_alabama_montgomery_countryside_00007.png */; };\n\t\t03F752D724EED19C00945B1D /* video_inspire_california_big-sur_2020_00001.png in Resources */ = {isa = PBXBuildFile; fileRef = 03F752D024EED19C00945B1D /* video_inspire_california_big-sur_2020_00001.png */; };\n\t\t03F752D824EED19C00945B1D /* video_inspire_california_big-sur_2020_00001.png in Resources */ = {isa = PBXBuildFile; fileRef = 03F752D024EED19C00945B1D /* video_inspire_california_big-sur_2020_00001.png */; };\n\t\t03F752D924EED19C00945B1D /* video_inspire_california_big-sur_2020_00001.png in Resources */ = {isa = PBXBuildFile; fileRef = 03F752D024EED19C00945B1D /* video_inspire_california_big-sur_2020_00001.png */; };\n\t\t03F752DA24EED19C00945B1D /* video_inspire_california_big-sur_2020_00001.png in Resources */ = {isa = PBXBuildFile; fileRef = 03F752D024EED19C00945B1D /* video_inspire_california_big-sur_2020_00001.png */; };\n\t\t03F752DB24EED19C00945B1D /* video_inspire_italy_como_cerano-dintelvi_006.png in Resources */ = {isa = PBXBuildFile; fileRef = 03F752D124EED19C00945B1D /* video_inspire_italy_como_cerano-dintelvi_006.png */; };\n\t\t03F752DC24EED19C00945B1D /* video_inspire_italy_como_cerano-dintelvi_006.png in Resources */ = {isa = PBXBuildFile; fileRef = 03F752D124EED19C00945B1D /* video_inspire_italy_como_cerano-dintelvi_006.png */; };\n\t\t03F752DD24EED19C00945B1D /* video_inspire_italy_como_cerano-dintelvi_006.png in Resources */ = {isa = PBXBuildFile; fileRef = 03F752D124EED19C00945B1D /* video_inspire_italy_como_cerano-dintelvi_006.png */; };\n\t\t03F752DE24EED19C00945B1D /* video_inspire_italy_como_cerano-dintelvi_006.png in Resources */ = {isa = PBXBuildFile; fileRef = 03F752D124EED19C00945B1D /* video_inspire_italy_como_cerano-dintelvi_006.png */; };\n\t\t03F752DF24EED19C00945B1D /* video_inspire_california_catalina_00005.png in Resources */ = {isa = PBXBuildFile; fileRef = 03F752D224EED19C00945B1D /* video_inspire_california_catalina_00005.png */; };\n\t\t03F752E024EED19C00945B1D /* video_inspire_california_catalina_00005.png in Resources */ = {isa = PBXBuildFile; fileRef = 03F752D224EED19C00945B1D /* video_inspire_california_catalina_00005.png */; };\n\t\t03F752E124EED19C00945B1D /* video_inspire_california_catalina_00005.png in Resources */ = {isa = PBXBuildFile; fileRef = 03F752D224EED19C00945B1D /* video_inspire_california_catalina_00005.png */; };\n\t\t03F752E224EED19C00945B1D /* video_inspire_california_catalina_00005.png in Resources */ = {isa = PBXBuildFile; fileRef = 03F752D224EED19C00945B1D /* video_inspire_california_catalina_00005.png */; };\n\t\t03F752E424EED21100945B1D /* video_inspire_california_vineyard_sierra-mar_sunrise_110.png in Resources */ = {isa = PBXBuildFile; fileRef = 03F752E324EED21100945B1D /* video_inspire_california_vineyard_sierra-mar_sunrise_110.png */; };\n\t\t03F752E524EED21100945B1D /* video_inspire_california_vineyard_sierra-mar_sunrise_110.png in Resources */ = {isa = PBXBuildFile; fileRef = 03F752E324EED21100945B1D /* video_inspire_california_vineyard_sierra-mar_sunrise_110.png */; };\n\t\t03F752E624EED21100945B1D /* video_inspire_california_vineyard_sierra-mar_sunrise_110.png in Resources */ = {isa = PBXBuildFile; fileRef = 03F752E324EED21100945B1D /* video_inspire_california_vineyard_sierra-mar_sunrise_110.png */; };\n\t\t03F752E724EED21100945B1D /* video_inspire_california_vineyard_sierra-mar_sunrise_110.png in Resources */ = {isa = PBXBuildFile; fileRef = 03F752E324EED21100945B1D /* video_inspire_california_vineyard_sierra-mar_sunrise_110.png */; };\n\t\t03F752E924EEFC3100945B1D /* text.cursor.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03F752E824EEFC3100945B1D /* text.cursor.pdf */; };\n\t\t03F752EA24EEFC3100945B1D /* text.cursor.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03F752E824EEFC3100945B1D /* text.cursor.pdf */; };\n\t\t03F752EB24EEFC3100945B1D /* text.cursor.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03F752E824EEFC3100945B1D /* text.cursor.pdf */; };\n\t\t03F752EC24EEFC3100945B1D /* text.cursor.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03F752E824EEFC3100945B1D /* text.cursor.pdf */; };\n\t\t03F752EE24EEFC8500945B1D /* house.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03F752ED24EEFC8500945B1D /* house.pdf */; };\n\t\t03F752EF24EEFC8500945B1D /* house.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03F752ED24EEFC8500945B1D /* house.pdf */; };\n\t\t03F752F024EEFC8500945B1D /* house.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03F752ED24EEFC8500945B1D /* house.pdf */; };\n\t\t03F752F124EEFC8500945B1D /* house.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 03F752ED24EEFC8500945B1D /* house.pdf */; };\n\t\t03FA49A12423DA1F00863AF6 /* TimerLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03FA49A02423DA1F00863AF6 /* TimerLayer.swift */; };\n\t\t03FA49A22423DA1F00863AF6 /* TimerLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03FA49A02423DA1F00863AF6 /* TimerLayer.swift */; };\n\t\t03FA49B22423DA7D00863AF6 /* InfoTimerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 030DDA8F2423C3BE0072D5C9 /* InfoTimerView.swift */; };\n\t\t03FA49B42428EE3300863AF6 /* InfoDateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03FA49B32428EE3300863AF6 /* InfoDateView.swift */; };\n\t\t03FA49B52428EE3300863AF6 /* InfoDateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03FA49B32428EE3300863AF6 /* InfoDateView.swift */; };\n\t\t03FA49B72428F84500863AF6 /* DateLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03FA49B62428F84500863AF6 /* DateLayer.swift */; };\n\t\t03FA49B82428F84500863AF6 /* DateLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03FA49B62428F84500863AF6 /* DateLayer.swift */; };\n\t\t03FF1930269709AB00A0FA7F /* PlaybackSpeed.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03FF192F269709AB00A0FA7F /* PlaybackSpeed.swift */; };\n\t\t03FF1931269709AB00A0FA7F /* PlaybackSpeed.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03FF192F269709AB00A0FA7F /* PlaybackSpeed.swift */; };\n\t\t03FF1932269709AB00A0FA7F /* PlaybackSpeed.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03FF192F269709AB00A0FA7F /* PlaybackSpeed.swift */; };\n\t\tAA7E2E5E1FC62E8B00E5F320 /* AerialPlayerItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA7E2E5D1FC62E8B00E5F320 /* AerialPlayerItem.swift */; };\n\t\tF0058B8228ABF69B0053699B /* SoundOutputManager+Goodies.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0058B7E28ABF69B0053699B /* SoundOutputManager+Goodies.swift */; };\n\t\tF0058B8328ABF69B0053699B /* SoundOutputManager+Goodies.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0058B7E28ABF69B0053699B /* SoundOutputManager+Goodies.swift */; };\n\t\tF0058B8428ABF69B0053699B /* SoundOutputManager+Goodies.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0058B7E28ABF69B0053699B /* SoundOutputManager+Goodies.swift */; };\n\t\tF0058B8528ABF69B0053699B /* SoundOutputManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0058B7F28ABF69B0053699B /* SoundOutputManager.swift */; };\n\t\tF0058B8628ABF69B0053699B /* SoundOutputManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0058B7F28ABF69B0053699B /* SoundOutputManager.swift */; };\n\t\tF0058B8728ABF69B0053699B /* SoundOutputManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0058B7F28ABF69B0053699B /* SoundOutputManager.swift */; };\n\t\tF0058B8828ABF69B0053699B /* Sound.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0058B8028ABF69B0053699B /* Sound.swift */; };\n\t\tF0058B8928ABF69B0053699B /* Sound.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0058B8028ABF69B0053699B /* Sound.swift */; };\n\t\tF0058B8A28ABF69B0053699B /* Sound.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0058B8028ABF69B0053699B /* Sound.swift */; };\n\t\tF0058B8B28ABF69B0053699B /* SoundOutputManager+Properties.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0058B8128ABF69B0053699B /* SoundOutputManager+Properties.swift */; };\n\t\tF0058B8C28ABF69B0053699B /* SoundOutputManager+Properties.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0058B8128ABF69B0053699B /* SoundOutputManager+Properties.swift */; };\n\t\tF0058B8D28ABF69B0053699B /* SoundOutputManager+Properties.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0058B8128ABF69B0053699B /* SoundOutputManager+Properties.swift */; };\n\t\tF00864B423AAE7F0003210EF /* DarkMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = F00864B323AAE7F0003210EF /* DarkMode.swift */; };\n\t\tF00864B523AAE7F0003210EF /* DarkMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = F00864B323AAE7F0003210EF /* DarkMode.swift */; };\n\t\tF00864B723AAE8E9003210EF /* NightShift.swift in Sources */ = {isa = PBXBuildFile; fileRef = F00864B623AAE8E9003210EF /* NightShift.swift */; };\n\t\tF00864B823AAE8E9003210EF /* NightShift.swift in Sources */ = {isa = PBXBuildFile; fileRef = F00864B623AAE8E9003210EF /* NightShift.swift */; };\n\t\tF008DAFD23AADCFB00739DE1 /* Brightness.swift in Sources */ = {isa = PBXBuildFile; fileRef = F008DAFC23AADCFB00739DE1 /* Brightness.swift */; };\n\t\tF008DAFE23AADCFB00739DE1 /* Brightness.swift in Sources */ = {isa = PBXBuildFile; fileRef = F008DAFC23AADCFB00739DE1 /* Brightness.swift */; };\n\t\tF05E805428AE8A9C0088B9C5 /* NowPlayingCollectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F05E805328AE8A9C0088B9C5 /* NowPlayingCollectionView.swift */; };\n\t\tF05E805528AE8A9C0088B9C5 /* NowPlayingCollectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F05E805328AE8A9C0088B9C5 /* NowPlayingCollectionView.swift */; };\n\t\tF05E805628AE8A9C0088B9C5 /* NowPlayingCollectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F05E805328AE8A9C0088B9C5 /* NowPlayingCollectionView.swift */; };\n\t\tF06FCF1A28DB8673007558BA /* tl.json in Resources */ = {isa = PBXBuildFile; fileRef = F06FCF1928DB8673007558BA /* tl.json */; };\n\t\tF06FCF1B28DB8673007558BA /* tl.json in Resources */ = {isa = PBXBuildFile; fileRef = F06FCF1928DB8673007558BA /* tl.json */; };\n\t\tF06FCF1C28DB8673007558BA /* tl.json in Resources */ = {isa = PBXBuildFile; fileRef = F06FCF1928DB8673007558BA /* tl.json */; };\n\t\tF07221872AD4354E001F5452 /* CompanionBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = F07221862AD4354E001F5452 /* CompanionBridge.swift */; };\n\t\tF07221882AD4354E001F5452 /* CompanionBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = F07221862AD4354E001F5452 /* CompanionBridge.swift */; };\n\t\tF07221892AD4354E001F5452 /* CompanionBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = F07221862AD4354E001F5452 /* CompanionBridge.swift */; };\n\t\tF0A3E0A32884683D005E8D8D /* CompanionCacheViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0A3E0A12884683D005E8D8D /* CompanionCacheViewController.swift */; };\n\t\tF0A3E0A42884683D005E8D8D /* CompanionCacheViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0A3E0A12884683D005E8D8D /* CompanionCacheViewController.swift */; };\n\t\tF0A3E0A52884683D005E8D8D /* CompanionCacheViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0A3E0A12884683D005E8D8D /* CompanionCacheViewController.swift */; };\n\t\tF0A3E0A62884683D005E8D8D /* CompanionCacheViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = F0A3E0A22884683D005E8D8D /* CompanionCacheViewController.xib */; };\n\t\tF0A3E0A72884683D005E8D8D /* CompanionCacheViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = F0A3E0A22884683D005E8D8D /* CompanionCacheViewController.xib */; };\n\t\tF0A3E0A82884683D005E8D8D /* CompanionCacheViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = F0A3E0A22884683D005E8D8D /* CompanionCacheViewController.xib */; };\n\t\tFA143CE61BDA3EEF0041A82B /* AVKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA143CE51BDA3EEF0041A82B /* AVKit.framework */; };\n\t\tFA36BD3F1BE57F8E00D5E03B /* VideoDownload.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA36BD3E1BE57F8E00D5E03B /* VideoDownload.swift */; };\n\t\tFA36BD401BE57F8E00D5E03B /* VideoDownload.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA36BD3E1BE57F8E00D5E03B /* VideoDownload.swift */; };\n\t\tFA7199711D94EC5A00FBC99B /* PreferencesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA7199701D94EC5A00FBC99B /* PreferencesTests.swift */; };\n\t\tFAB22A7E1BE17D7D0065C0F5 /* AssetLoaderDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAB22A7D1BE17D7D0065C0F5 /* AssetLoaderDelegate.swift */; };\n\t\tFAB22A7F1BE17D7D0065C0F5 /* AssetLoaderDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAB22A7D1BE17D7D0065C0F5 /* AssetLoaderDelegate.swift */; };\n\t\tFAC36F481BE1756D007F2A20 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = FAC36F321BE1756D007F2A20 /* Assets.xcassets */; };\n\t\tFAC36F4A1BE1756D007F2A20 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = FAC36F331BE1756D007F2A20 /* MainMenu.xib */; };\n\t\tFAC36F591BE1756D007F2A20 /* AerialVideo.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAC36F401BE1756D007F2A20 /* AerialVideo.swift */; };\n\t\tFAC36F5A1BE1756D007F2A20 /* AerialVideo.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAC36F401BE1756D007F2A20 /* AerialVideo.swift */; };\n\t\tFAC36F5B1BE1756D007F2A20 /* AerialView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAC36F431BE1756D007F2A20 /* AerialView.swift */; };\n\t\tFAC36F5C1BE1756D007F2A20 /* AerialView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAC36F431BE1756D007F2A20 /* AerialView.swift */; };\n\t\tFAC36F5D1BE1756D007F2A20 /* CheckCellView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAC36F441BE1756D007F2A20 /* CheckCellView.swift */; };\n\t\tFAC36F5E1BE1756D007F2A20 /* CheckCellView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAC36F441BE1756D007F2A20 /* CheckCellView.swift */; };\n\t\tFAC36F601BE175CF007F2A20 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAC36F301BE1756D007F2A20 /* AppDelegate.swift */; };\n\t\tFAC36F671BE1778C007F2A20 /* ManifestLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAC36F661BE1778C007F2A20 /* ManifestLoader.swift */; };\n\t\tFAC36F681BE1778C007F2A20 /* ManifestLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAC36F661BE1778C007F2A20 /* ManifestLoader.swift */; };\n\t\tFAF450211BE2B45D00C1F98A /* VideoLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAF450201BE2B45D00C1F98A /* VideoLoader.swift */; };\n\t\tFAF450221BE2B45D00C1F98A /* VideoLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAF450201BE2B45D00C1F98A /* VideoLoader.swift */; };\n\t\tFAF450241BE2D2FD00C1F98A /* VideoCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAF450231BE2D2FD00C1F98A /* VideoCache.swift */; };\n\t\tFAF450251BE2D2FD00C1F98A /* VideoCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAF450231BE2D2FD00C1F98A /* VideoCache.swift */; };\n/* End PBXBuildFile section */\n\n/* Begin PBXContainerItemProxy section */\n\t\tFA7199731D94EC5A00FBC99B /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = FACAF19C1BD9FC6000E539DC /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = FA143CD51BDA3E880041A82B;\n\t\t\tremoteInfo = \"Aerial App\";\n\t\t};\n/* End PBXContainerItemProxy section */\n\n/* Begin PBXCopyFilesBuildPhase section */\n\t\t034116CE23F9AD0100CD7674 /* Embed Frameworks */ = {\n\t\t\tisa = PBXCopyFilesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tdstPath = \"\";\n\t\t\tdstSubfolderSpec = 10;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tname = \"Embed Frameworks\";\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t034116D123F9AD0600CD7674 /* Embed Frameworks */ = {\n\t\t\tisa = PBXCopyFilesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tdstPath = \"\";\n\t\t\tdstSubfolderSpec = 10;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tname = \"Embed Frameworks\";\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t0396D5AE24B8B7ED00CC021B /* Embed Frameworks */ = {\n\t\t\tisa = PBXCopyFilesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tdstPath = \"\";\n\t\t\tdstSubfolderSpec = 10;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tname = \"Embed Frameworks\";\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXCopyFilesBuildPhase section */\n\n/* Begin PBXFileReference section */\n\t\t0300109624D6EF4C0092AE68 /* AVPlayerItem+vibrance.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = \"AVPlayerItem+vibrance.swift\"; sourceTree = \"<group>\"; };\n\t\t030010A124D706DB0092AE68 /* SidebarOutlineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SidebarOutlineView.swift; sourceTree = \"<group>\"; };\n\t\t030010A524D718D30092AE68 /* slider.horizontal.3.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = slider.horizontal.3.pdf; sourceTree = \"<group>\"; };\n\t\t030010A924D71EB20092AE68 /* FiltersViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FiltersViewController.swift; sourceTree = \"<group>\"; };\n\t\t030010AA24D71EB20092AE68 /* FiltersViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = FiltersViewController.xib; sourceTree = \"<group>\"; };\n\t\t0300B7CA24D1B531006132E5 /* person.3.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = person.3.pdf; sourceTree = \"<group>\"; };\n\t\t0300B7CB24D1B531006132E5 /* bubble.left.and.bubble.right.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = bubble.left.and.bubble.right.pdf; sourceTree = \"<group>\"; };\n\t\t0300B7CC24D1B531006132E5 /* helm.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = helm.pdf; sourceTree = \"<group>\"; };\n\t\t0300B7CD24D1B532006132E5 /* gear.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = gear.pdf; sourceTree = \"<group>\"; };\n\t\t0300B7CE24D1B532006132E5 /* eye.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = eye.pdf; sourceTree = \"<group>\"; };\n\t\t0300B7CF24D1B532006132E5 /* text.bubble.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = text.bubble.pdf; sourceTree = \"<group>\"; };\n\t\t0300B7D024D1B532006132E5 /* circle.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = circle.pdf; sourceTree = \"<group>\"; };\n\t\t0300B7D124D1B532006132E5 /* star.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = star.pdf; sourceTree = \"<group>\"; };\n\t\t0300B7D224D1B532006132E5 /* clock.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = clock.pdf; sourceTree = \"<group>\"; };\n\t\t0300B7D324D1B532006132E5 /* sparkles.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = sparkles.pdf; sourceTree = \"<group>\"; };\n\t\t0300B7D424D1B533006132E5 /* film.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = film.pdf; sourceTree = \"<group>\"; };\n\t\t0300B7D524D1B533006132E5 /* eye.slash.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = eye.slash.pdf; sourceTree = \"<group>\"; };\n\t\t0300B7D624D1B533006132E5 /* info.circle.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = info.circle.pdf; sourceTree = \"<group>\"; };\n\t\t0300B7D724D1B533006132E5 /* regular.moon.stars.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = regular.moon.stars.pdf; sourceTree = \"<group>\"; };\n\t\t0300B7D824D1B533006132E5 /* antenna.radiowaves.left.and.right.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = antenna.radiowaves.left.and.right.pdf; sourceTree = \"<group>\"; };\n\t\t0300B7D924D1B533006132E5 /* sunset.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = sunset.pdf; sourceTree = \"<group>\"; };\n\t\t0300B7DA24D1B534006132E5 /* tram.fill.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = tram.fill.pdf; sourceTree = \"<group>\"; };\n\t\t0300B7DB24D1B534006132E5 /* arrow.down.circle.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = arrow.down.circle.pdf; sourceTree = \"<group>\"; };\n\t\t0300B7DC24D1B534006132E5 /* flame.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = flame.pdf; sourceTree = \"<group>\"; };\n\t\t0300B7DD24D1B534006132E5 /* regular.sun.min.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = regular.sun.min.pdf; sourceTree = \"<group>\"; };\n\t\t0300B7DE24D1B534006132E5 /* mappin.and.ellipse.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = mappin.and.ellipse.pdf; sourceTree = \"<group>\"; };\n\t\t0300B7DF24D1B534006132E5 /* arrow.down.circle.fill.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = arrow.down.circle.fill.pdf; sourceTree = \"<group>\"; };\n\t\t0300B7E024D1B535006132E5 /* location.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = location.pdf; sourceTree = \"<group>\"; };\n\t\t0300B7E124D1B535006132E5 /* tv.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = tv.pdf; sourceTree = \"<group>\"; };\n\t\t0300B7E224D1B535006132E5 /* sunrise.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = sunrise.pdf; sourceTree = \"<group>\"; };\n\t\t0300B7E324D1B535006132E5 /* star.fill.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = star.fill.pdf; sourceTree = \"<group>\"; };\n\t\t0300B7E424D1B535006132E5 /* regular.cloud.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = regular.cloud.pdf; sourceTree = \"<group>\"; };\n\t\t0300B7E524D1B535006132E5 /* regular.sun.max.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = regular.sun.max.pdf; sourceTree = \"<group>\"; };\n\t\t0300B7E624D1B536006132E5 /* dial.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = dial.pdf; sourceTree = \"<group>\"; };\n\t\t0300B7E724D1B536006132E5 /* checkmark.circle.fill.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = checkmark.circle.fill.pdf; sourceTree = \"<group>\"; };\n\t\t0300B7E824D1B536006132E5 /* square.and.arrow.down.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = square.and.arrow.down.pdf; sourceTree = \"<group>\"; };\n\t\t0300B84724D1FD24006132E5 /* FirstSetupWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FirstSetupWindowController.swift; sourceTree = \"<group>\"; };\n\t\t0300B84824D1FD24006132E5 /* FirstSetupWindowController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = FirstSetupWindowController.xib; sourceTree = \"<group>\"; };\n\t\t0300B85F24D2052B006132E5 /* WelcomeViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WelcomeViewController.swift; sourceTree = \"<group>\"; };\n\t\t0300B86024D2052B006132E5 /* WelcomeViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = WelcomeViewController.xib; sourceTree = \"<group>\"; };\n\t\t0300B86724D20B12006132E5 /* NextViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NextViewController.swift; sourceTree = \"<group>\"; };\n\t\t0300B86824D20B12006132E5 /* NextViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NextViewController.xib; sourceTree = \"<group>\"; };\n\t\t030473C924BCA9A40094A1A6 /* VideoViewItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoViewItem.swift; sourceTree = \"<group>\"; };\n\t\t03047A5324D2DD8E000EFE62 /* NSMenuItem+icons.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = \"NSMenuItem+icons.swift\"; sourceTree = \"<group>\"; };\n\t\t0306336723A1012200046A59 /* LocationLayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationLayer.swift; sourceTree = \"<group>\"; };\n\t\t0306336A23A142FA00046A59 /* LayerOffsets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LayerOffsets.swift; sourceTree = \"<group>\"; };\n\t\t0306336D23A15FA900046A59 /* AnimationTextLayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnimationTextLayer.swift; sourceTree = \"<group>\"; };\n\t\t03075EA824ED794F00FDBE48 /* trash.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = trash.pdf; sourceTree = \"<group>\"; };\n\t\t03075EB024ED794F00FDBE48 /* textformat.alt.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = textformat.alt.pdf; sourceTree = \"<group>\"; };\n\t\t030A0F28245C7C7D009E1D97 /* BatteryIconLayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BatteryIconLayer.swift; sourceTree = \"<group>\"; };\n\t\t030B5E32229FDD26008F2910 /* AutoUpdates.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = AutoUpdates.md; sourceTree = \"<group>\"; };\n\t\t030DDA8F2423C3BE0072D5C9 /* InfoTimerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfoTimerView.swift; sourceTree = \"<group>\"; };\n\t\t0313329A24BF3FA700C84A05 /* SidebarViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SidebarViewController.swift; sourceTree = \"<group>\"; };\n\t\t0313329B24BF3FA700C84A05 /* SidebarViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = SidebarViewController.xib; sourceTree = \"<group>\"; };\n\t\t0313F9E522942AA500B074BB /* CustomVideos.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = CustomVideos.xib; sourceTree = \"<group>\"; };\n\t\t0313F9E722942B4500B074BB /* CustomVideoController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomVideoController.swift; sourceTree = \"<group>\"; };\n\t\t0313F9EB2294468600B074BB /* SeededGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeededGenerator.swift; sourceTree = \"<group>\"; };\n\t\t0313F9EE22955F3B00B074BB /* CustomVideoFolders.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomVideoFolders.swift; sourceTree = \"<group>\"; };\n\t\t0317C19B268B65D10082A40C /* Music.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Music.swift; sourceTree = \"<group>\"; };\n\t\t031945F124CCC48C00F37B35 /* CreditsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreditsViewController.swift; sourceTree = \"<group>\"; };\n\t\t031945F224CCC48C00F37B35 /* CreditsViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = CreditsViewController.xib; sourceTree = \"<group>\"; };\n\t\t031945F924CCC52600F37B35 /* HelpViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HelpViewController.swift; sourceTree = \"<group>\"; };\n\t\t031945FA24CCC52600F37B35 /* HelpViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = HelpViewController.xib; sourceTree = \"<group>\"; };\n\t\t0319460824D1A09F00F37B35 /* icon-320@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = \"icon-320@2x.png\"; sourceTree = \"<group>\"; };\n\t\t031C5CB7268CA4E700CE35B4 /* ArtworkLayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArtworkLayer.swift; sourceTree = \"<group>\"; };\n\t\t031FB78A248A87330054BAFD /* PrefsCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrefsCache.swift; sourceTree = \"<group>\"; };\n\t\t0321A53224D44E80004F1975 /* ActionCellView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionCellView.swift; sourceTree = \"<group>\"; };\n\t\t0321A53D24D4515B004F1975 /* folder.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = folder.pdf; sourceTree = \"<group>\"; };\n\t\t0321A54324D5C863004F1975 /* NSButton+icons.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = \"NSButton+icons.swift\"; sourceTree = \"<group>\"; };\n\t\t03233B67217272640077D3F9 /* PoiStringProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PoiStringProvider.swift; sourceTree = \"<group>\"; };\n\t\t032851F6260A4C2B00684A81 /* OneCall.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OneCall.swift; sourceTree = \"<group>\"; };\n\t\t032851FA260A625100684A81 /* ForecastLayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ForecastLayer.swift; sourceTree = \"<group>\"; };\n\t\t03298773274687340036D898 /* NowPlayingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NowPlayingViewController.swift; sourceTree = \"<group>\"; };\n\t\t03298774274687340036D898 /* NowPlayingViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NowPlayingViewController.xib; sourceTree = \"<group>\"; };\n\t\t032D1160239A7D82007E7756 /* Battery.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Battery.swift; sourceTree = \"<group>\"; };\n\t\t032D1163239A7F0C007E7756 /* AerialView+Brightness.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = \"AerialView+Brightness.swift\"; sourceTree = \"<group>\"; };\n\t\t032E099C24C3897E00387230 /* AdvancedViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdvancedViewController.swift; sourceTree = \"<group>\"; };\n\t\t032E099D24C3897E00387230 /* AdvancedViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = AdvancedViewController.xib; sourceTree = \"<group>\"; };\n\t\t0332076C26D7C355001F9837 /* AVAsset+VideoOrientation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = \"AVAsset+VideoOrientation.swift\"; sourceTree = \"<group>\"; };\n\t\t0338119424C1D15B002E23E0 /* Aerial.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Aerial.swift; sourceTree = \"<group>\"; };\n\t\t033811AE24C1E243002E23E0 /* InfoViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfoViewController.swift; sourceTree = \"<group>\"; };\n\t\t033811AF24C1E243002E23E0 /* InfoViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = InfoViewController.xib; sourceTree = \"<group>\"; };\n\t\t033842E024489D7300A2C523 /* WeatherLayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WeatherLayer.swift; sourceTree = \"<group>\"; };\n\t\t033D68802453080C0016F837 /* ConditionSymbolLayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConditionSymbolLayer.swift; sourceTree = \"<group>\"; };\n\t\t034116D223F9BD3100CD7674 /* PrefsUpdates.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrefsUpdates.swift; sourceTree = \"<group>\"; };\n\t\t0343E9F82630590A00AC702F /* openweather_logo.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = openweather_logo.png; sourceTree = \"<group>\"; };\n\t\t0345872C2449C52F00C97D1B /* AnimatableLayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnimatableLayer.swift; sourceTree = \"<group>\"; };\n\t\t034587312449D8EB00C97D1B /* AnimationLayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnimationLayer.swift; sourceTree = \"<group>\"; };\n\t\t0345CFEB24BF43280001045C /* VideosViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideosViewController.swift; sourceTree = \"<group>\"; };\n\t\t0345CFEC24BF43280001045C /* VideosViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = VideosViewController.xib; sourceTree = \"<group>\"; };\n\t\t0345D00924BF4E8C0001045C /* Sidebar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Sidebar.swift; sourceTree = \"<group>\"; };\n\t\t0345D00D24C07CC70001045C /* VideoCellView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoCellView.swift; sourceTree = \"<group>\"; };\n\t\t0345EDE624C3239400C73038 /* DisplaysViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisplaysViewController.swift; sourceTree = \"<group>\"; };\n\t\t0345EDE724C3239400C73038 /* DisplaysViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = DisplaysViewController.xib; sourceTree = \"<group>\"; };\n\t\t034A6DC124ACC7C800D62129 /* SourceList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SourceList.swift; sourceTree = \"<group>\"; };\n\t\t034A6DC324ACC80200D62129 /* Source.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Source.swift; sourceTree = \"<group>\"; };\n\t\t034DEE2C24BF1BC700A2D3CD /* PanelWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PanelWindowController.swift; sourceTree = \"<group>\"; };\n\t\t034DEE2D24BF1BC700A2D3CD /* PanelWindowController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = PanelWindowController.xib; sourceTree = \"<group>\"; };\n\t\t034F29B623A7A93D004B34D5 /* InfoTableSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfoTableSource.swift; sourceTree = \"<group>\"; };\n\t\t034F29BE23A7E28E004B34D5 /* PrefsInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrefsInfo.swift; sourceTree = \"<group>\"; };\n\t\t0350CB78279481F2005F8625 /* hu.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = hu.json; sourceTree = \"<group>\"; };\n\t\t03510C6A21834EB2008F74F2 /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; };\n\t\t03510C6D21834F38008F74F2 /* Aerial-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = \"Aerial-Bridging-Header.h\"; sourceTree = \"<group>\"; };\n\t\t03510C6E21834F38008F74F2 /* IOBridge.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = IOBridge.m; sourceTree = \"<group>\"; };\n\t\t03510C722185EF76008F74F2 /* CoreLocation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreLocation.framework; path = System/Library/Frameworks/CoreLocation.framework; sourceTree = SDKROOT; };\n\t\t0354D0E823F6C31800D86F9E /* InfoSettingsTableSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfoSettingsTableSource.swift; sourceTree = \"<group>\"; };\n\t\t0354D0EB23F6CB7B00D86F9E /* InfoSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfoSettingsView.swift; sourceTree = \"<group>\"; };\n\t\t035D524E239AA31A00DC29DC /* AerialView+Player.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = \"AerialView+Player.swift\"; sourceTree = \"<group>\"; };\n\t\t03608A2B22A56465008F08A2 /* HardwareDetection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HardwareDetection.swift; sourceTree = \"<group>\"; };\n\t\t0361B9A723D732A300B6252D /* PrefsDisplays.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrefsDisplays.swift; sourceTree = \"<group>\"; };\n\t\t0361B9AA23D73D4500B6252D /* PrefsTime.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrefsTime.swift; sourceTree = \"<group>\"; };\n\t\t0369985C2196103300E359D3 /* missingvideos.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = missingvideos.json; sourceTree = \"<group>\"; };\n\t\t036A57D423F30DD00009DC02 /* DownloadIndicatorLayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownloadIndicatorLayer.swift; sourceTree = \"<group>\"; };\n\t\t036A57D723F470940009DC02 /* InfoCountdownView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfoCountdownView.swift; sourceTree = \"<group>\"; };\n\t\t036A57DA23F5820A0009DC02 /* CountdownLayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CountdownLayer.swift; sourceTree = \"<group>\"; };\n\t\t036A7E9A26370C260019186B /* Forecast.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Forecast.swift; sourceTree = \"<group>\"; };\n\t\t0374C9FD247AC5BC002F29D3 /* Locations.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Locations.swift; sourceTree = \"<group>\"; };\n\t\t037772DF24E43AF300D81EEA /* TimeSetupViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimeSetupViewController.swift; sourceTree = \"<group>\"; };\n\t\t037772E024E43AF300D81EEA /* TimeSetupViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = TimeSetupViewController.xib; sourceTree = \"<group>\"; };\n\t\t037772E724E44BB100D81EEA /* xmark.circle.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = xmark.circle.pdf; sourceTree = \"<group>\"; };\n\t\t037772EB24E44CE100D81EEA /* RecapViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecapViewController.swift; sourceTree = \"<group>\"; };\n\t\t037772EC24E44CE100D81EEA /* RecapViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = RecapViewController.xib; sourceTree = \"<group>\"; };\n\t\t037772F424E4668600D81EEA /* aspectratio.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = aspectratio.pdf; sourceTree = \"<group>\"; };\n\t\t0377BF6F24BA15E600C33F9F /* btn_donate.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = btn_donate.png; sourceTree = \"<group>\"; };\n\t\t0378985C24C35F8A009B9418 /* CacheViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CacheViewController.swift; sourceTree = \"<group>\"; };\n\t\t0378985D24C35F8A009B9418 /* CacheViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = CacheViewController.xib; sourceTree = \"<group>\"; };\n\t\t0385FC58242B9AE1007E6513 /* APISecrets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = APISecrets.swift; sourceTree = \"<group>\"; };\n\t\t0385FC5C242B9F6E007E6513 /* InfoWeatherView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfoWeatherView.swift; sourceTree = \"<group>\"; };\n\t\t03893CB2217749F0008E7125 /* ErrorLog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorLog.swift; sourceTree = \"<group>\"; };\n\t\t038C584623A9304800224630 /* InfoContainerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfoContainerView.swift; sourceTree = \"<group>\"; };\n\t\t038C584923A9394000224630 /* InfoCommonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfoCommonView.swift; sourceTree = \"<group>\"; };\n\t\t038D2EDD23B0FB0D00CD91F7 /* PrefsVideos.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrefsVideos.swift; sourceTree = \"<group>\"; };\n\t\t038D2EE323B6565900CD91F7 /* InfoBatteryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfoBatteryView.swift; sourceTree = \"<group>\"; };\n\t\t03933B8924C3986800A98D94 /* SourcesViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SourcesViewController.swift; sourceTree = \"<group>\"; };\n\t\t03933B8A24C3986800A98D94 /* SourcesViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = SourcesViewController.xib; sourceTree = \"<group>\"; };\n\t\t039385792175D4B80040B850 /* AVPlayerViewExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AVPlayerViewExtension.swift; sourceTree = \"<group>\"; };\n\t\t03958348217F4416008E8F9C /* Solar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Solar.swift; sourceTree = \"<group>\"; };\n\t\t0395835121807D1F008E8F9C /* thumbnail@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = \"thumbnail@2x.png\"; sourceTree = \"<group>\"; };\n\t\t0395835221807D1F008E8F9C /* thumbnail.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = thumbnail.png; sourceTree = \"<group>\"; };\n\t\t0396D50624B8B7D700CC021B /* AerialApp copy-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = \"AerialApp copy-Info.plist\"; sourceTree = \"<group>\"; };\n\t\t0396D5B524B8B7ED00CC021B /* Aerial (low dependencies).saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = \"Aerial (low dependencies).saver\"; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t0396D5B624B8B7EE00CC021B /* Aerial copy-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = \"Aerial copy-Info.plist\"; sourceTree = \"<group>\"; };\n\t\t03977EE2250E6917008FBAFD /* sv.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = sv.json; sourceTree = \"<group>\"; };\n\t\t03977EE3250E6917008FBAFD /* ja.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = ja.json; sourceTree = \"<group>\"; };\n\t\t03977EE4250E6917008FBAFD /* pt.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = pt.json; sourceTree = \"<group>\"; };\n\t\t03977EE5250E6917008FBAFD /* zh_TW.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = zh_TW.json; sourceTree = \"<group>\"; };\n\t\t03977EE6250E6917008FBAFD /* pl.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = pl.json; sourceTree = \"<group>\"; };\n\t\t03977EE7250E6918008FBAFD /* de.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = de.json; sourceTree = \"<group>\"; };\n\t\t03977EE8250E6918008FBAFD /* fr.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = fr.json; sourceTree = \"<group>\"; };\n\t\t03977EE9250E6918008FBAFD /* es.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = es.json; sourceTree = \"<group>\"; };\n\t\t03977EEA250E6918008FBAFD /* pt_BR.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = pt_BR.json; sourceTree = \"<group>\"; };\n\t\t03977EEB250E6918008FBAFD /* it.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = it.json; sourceTree = \"<group>\"; };\n\t\t03977EEC250E6918008FBAFD /* he.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = he.json; sourceTree = \"<group>\"; };\n\t\t03977EED250E6918008FBAFD /* en.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = en.json; sourceTree = \"<group>\"; };\n\t\t03977EEE250E6918008FBAFD /* zh_CN.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = zh_CN.json; sourceTree = \"<group>\"; };\n\t\t03977EEF250E6918008FBAFD /* ar.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = ar.json; sourceTree = \"<group>\"; };\n\t\t03977EF0250E6918008FBAFD /* nl.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = nl.json; sourceTree = \"<group>\"; };\n\t\t03977F1F250E7165008FBAFD /* TimeMachine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimeMachine.swift; sourceTree = \"<group>\"; };\n\t\t03A2CB9B216BA9AF0061E8E8 /* VideoManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoManager.swift; sourceTree = \"<group>\"; };\n\t\t03A42A822449F5EA003B3012 /* white_retina.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = white_retina.png; sourceTree = \"<group>\"; };\n\t\t03A42A9B2449F601003B3012 /* purple_retina.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = purple_retina.png; sourceTree = \"<group>\"; };\n\t\t03A42A9F2449F959003B3012 /* YahooLogoLayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YahooLogoLayer.swift; sourceTree = \"<group>\"; };\n\t\t03A42AA2244A0E5F003B3012 /* ConditionLayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConditionLayer.swift; sourceTree = \"<group>\"; };\n\t\t03A4A80A2451CE2C00A1F7A3 /* NSImage+trim.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = \"NSImage+trim.swift\"; sourceTree = \"<group>\"; };\n\t\t03A4A80D2451D04C00A1F7A3 /* PrefsAdvanced.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrefsAdvanced.swift; sourceTree = \"<group>\"; };\n\t\t03A596D223AA750F0097EA66 /* InfoMessageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfoMessageView.swift; sourceTree = \"<group>\"; };\n\t\t03A596D423AA752F0097EA66 /* InfoClockView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfoClockView.swift; sourceTree = \"<group>\"; };\n\t\t03A596D823AB8F000097EA66 /* InfoLocationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfoLocationView.swift; sourceTree = \"<group>\"; };\n\t\t03A6D14525F109B900960135 /* OpenWeather.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenWeather.swift; sourceTree = \"<group>\"; };\n\t\t03A6D14E25F294C900960135 /* location.north.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = location.north.pdf; sourceTree = \"<group>\"; };\n\t\t03A6D15225F297CE00960135 /* WindDirectionLayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WindDirectionLayer.swift; sourceTree = \"<group>\"; };\n\t\t03AA27BC2614A6F800A4D2CF /* ko.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = ko.json; sourceTree = \"<group>\"; };\n\t\t03AA32612631A8F2002198C3 /* GeoCoding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeoCoding.swift; sourceTree = \"<group>\"; };\n\t\t03AA7A2524C84C6200A47970 /* cloud.bolt.rain.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = cloud.bolt.rain.pdf; sourceTree = \"<group>\"; };\n\t\t03AA7A3C24C84C6200A47970 /* wind.snow.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = wind.snow.pdf; sourceTree = \"<group>\"; };\n\t\t03AA7A3D24C84C6200A47970 /* snow.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = snow.pdf; sourceTree = \"<group>\"; };\n\t\t03AA7A3E24C84C6200A47970 /* moon.stars.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = moon.stars.pdf; sourceTree = \"<group>\"; };\n\t\t03AA7A3F24C84C6200A47970 /* cloud.heavyrain.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = cloud.heavyrain.pdf; sourceTree = \"<group>\"; };\n\t\t03AA7A4024C84C6200A47970 /* battery.0.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = battery.0.pdf; sourceTree = \"<group>\"; };\n\t\t03AA7A4124C84C6200A47970 /* wrench.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = wrench.pdf; sourceTree = \"<group>\"; };\n\t\t03AA7A4224C84C6200A47970 /* cloud.sun.rain.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = cloud.sun.rain.pdf; sourceTree = \"<group>\"; };\n\t\t03AA7A4324C84C6200A47970 /* sun.dust.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = sun.dust.pdf; sourceTree = \"<group>\"; };\n\t\t03AA7A4424C84C6200A47970 /* sun.max.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = sun.max.pdf; sourceTree = \"<group>\"; };\n\t\t03AA7A4524C84C6200A47970 /* cloud.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = cloud.pdf; sourceTree = \"<group>\"; };\n\t\t03AA7A4624C84C6200A47970 /* cloud.sun.bolt.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = cloud.sun.bolt.pdf; sourceTree = \"<group>\"; };\n\t\t03AA7A4724C84C6200A47970 /* thermometer.snowflake.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = thermometer.snowflake.pdf; sourceTree = \"<group>\"; };\n\t\t03AA7A4824C84C6200A47970 /* hurricane.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = hurricane.pdf; sourceTree = \"<group>\"; };\n\t\t03AA7A4924C84C6200A47970 /* cloud.fog.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = cloud.fog.pdf; sourceTree = \"<group>\"; };\n\t\t03AA7A4A24C84C6200A47970 /* thermometer.sun.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = thermometer.sun.pdf; sourceTree = \"<group>\"; };\n\t\t03AA7A4B24C84C6200A47970 /* tropicalstorm.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = tropicalstorm.pdf; sourceTree = \"<group>\"; };\n\t\t03AA7A4C24C84C6300A47970 /* moon.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = moon.pdf; sourceTree = \"<group>\"; };\n\t\t03AA7A4D24C84C6300A47970 /* sun.min.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = sun.min.pdf; sourceTree = \"<group>\"; };\n\t\t03AA7A4E24C84C6300A47970 /* smoke.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = smoke.pdf; sourceTree = \"<group>\"; };\n\t\t03AA7A4F24C84C6300A47970 /* cloud.snow.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = cloud.snow.pdf; sourceTree = \"<group>\"; };\n\t\t03AA7A5024C84C6300A47970 /* cloud.moon.rain.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = cloud.moon.rain.pdf; sourceTree = \"<group>\"; };\n\t\t03AA7A5124C84C6300A47970 /* cloud.hail.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = cloud.hail.pdf; sourceTree = \"<group>\"; };\n\t\t03AA7A5224C84C6300A47970 /* cloud.drizzle.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = cloud.drizzle.pdf; sourceTree = \"<group>\"; };\n\t\t03AA7A5324C84C6300A47970 /* cloud.rain.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = cloud.rain.pdf; sourceTree = \"<group>\"; };\n\t\t03AA7A5424C84C6300A47970 /* sun.haze.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = sun.haze.pdf; sourceTree = \"<group>\"; };\n\t\t03AA7A5524C84C6300A47970 /* tornado.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = tornado.pdf; sourceTree = \"<group>\"; };\n\t\t03AA7A5624C84C6300A47970 /* cloud.moon.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = cloud.moon.pdf; sourceTree = \"<group>\"; };\n\t\t03AA7A5724C84C6300A47970 /* cloud.moon.bolt.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = cloud.moon.bolt.pdf; sourceTree = \"<group>\"; };\n\t\t03AA7A5824C84C6300A47970 /* cloud.bolt.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = cloud.bolt.pdf; sourceTree = \"<group>\"; };\n\t\t03AA7A5924C84C6300A47970 /* bolt.fill.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = bolt.fill.pdf; sourceTree = \"<group>\"; };\n\t\t03AA7A5A24C84C6300A47970 /* cloud.sun.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = cloud.sun.pdf; sourceTree = \"<group>\"; };\n\t\t03AA7A5B24C84C6300A47970 /* cloud.sleet.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = cloud.sleet.pdf; sourceTree = \"<group>\"; };\n\t\t03AA7A5C24C84C6300A47970 /* wind.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = wind.pdf; sourceTree = \"<group>\"; };\n\t\t03AD45FE22981B0C00261325 /* CustomVideoFolders+helpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = \"CustomVideoFolders+helpers.swift\"; sourceTree = \"<group>\"; };\n\t\t03B8742024E41CF8008E3D1B /* CacheSetupViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CacheSetupViewController.swift; sourceTree = \"<group>\"; };\n\t\t03B8742124E41CF8008E3D1B /* CacheSetupViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = CacheSetupViewController.xib; sourceTree = \"<group>\"; };\n\t\t03B8742F24E42675008E3D1B /* wand.and.rays.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = wand.and.rays.pdf; sourceTree = \"<group>\"; };\n\t\t03B8743024E42675008E3D1B /* wand.and.stars.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = wand.and.stars.pdf; sourceTree = \"<group>\"; };\n\t\t03B8743124E42675008E3D1B /* hand.raised.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = hand.raised.pdf; sourceTree = \"<group>\"; };\n\t\t03BDBEA024C467EC00BBD5E9 /* BrightnessViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrightnessViewController.swift; sourceTree = \"<group>\"; };\n\t\t03BDBEA124C467EC00BBD5E9 /* BrightnessViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = BrightnessViewController.xib; sourceTree = \"<group>\"; };\n\t\t03BDBEBE24C4727C00BBD5E9 /* TimeViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimeViewController.swift; sourceTree = \"<group>\"; };\n\t\t03BDBEBF24C4727C00BBD5E9 /* TimeViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = TimeViewController.xib; sourceTree = \"<group>\"; };\n\t\t03BF179D24E2F29C0080EF34 /* VideoFormatViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoFormatViewController.swift; sourceTree = \"<group>\"; };\n\t\t03BF179E24E2F29C0080EF34 /* VideoFormatViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = VideoFormatViewController.xib; sourceTree = \"<group>\"; };\n\t\t03BF51BB23A2643C008AD373 /* LayerManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LayerManager.swift; sourceTree = \"<group>\"; };\n\t\t03BF51BE23A274CA008AD373 /* MessageLayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageLayer.swift; sourceTree = \"<group>\"; };\n\t\t03BF51C123A2978B008AD373 /* ClockLayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClockLayer.swift; sourceTree = \"<group>\"; };\n\t\t03C344FB24B778EE00906EA6 /* CheckboxCellView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckboxCellView.swift; sourceTree = \"<group>\"; };\n\t\t03C344FE24B7A22300906EA6 /* DescriptionCellView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DescriptionCellView.swift; sourceTree = \"<group>\"; };\n\t\t03C605DB277B45CA005CA51F /* DispatchQueue+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = \"DispatchQueue+Extension.swift\"; sourceTree = \"<group>\"; };\n\t\t03C97BA624B5F74900739CED /* VideoList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoList.swift; sourceTree = \"<group>\"; };\n\t\t03C97BBF24B60E2F00739CED /* FileHelpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = FileHelpers.swift; path = Downloads/FileHelpers.swift; sourceTree = \"<group>\"; };\n\t\t03C97BC224B6210500739CED /* SourceInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SourceInfo.swift; sourceTree = \"<group>\"; };\n\t\t03D1E78622842FB300D10CF7 /* DisplayView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = DisplayView.swift; path = Aerial/Source/Views/PrefPanel/DisplayView.swift; sourceTree = SOURCE_ROOT; };\n\t\t03D1E7892284471A00D10CF7 /* DisplayDetection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisplayDetection.swift; sourceTree = \"<group>\"; };\n\t\t03D1E78E22848F7F00D10CF7 /* screen2.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = screen2.jpg; sourceTree = \"<group>\"; };\n\t\t03D1E78F22848F7F00D10CF7 /* screen1.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = screen1.jpg; sourceTree = \"<group>\"; };\n\t\t03D1E79022848F7F00D10CF7 /* screen0.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = screen0.jpg; sourceTree = \"<group>\"; };\n\t\t03D3A10C24C5D7CC0091FE99 /* Thumbnails.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Thumbnails.swift; sourceTree = \"<group>\"; };\n\t\t03D3A11224C5FC770091FE99 /* AspectFillNSImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AspectFillNSImageView.swift; sourceTree = \"<group>\"; };\n\t\t03D6C78922A0384F00DE830B /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = \"<group>\"; };\n\t\t03DAD46F229EAC66000DA6D1 /* Installation.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = Installation.md; sourceTree = \"<group>\"; };\n\t\t03DAD471229EB1E9000DA6D1 /* ChangeLog.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = ChangeLog.md; sourceTree = \"<group>\"; };\n\t\t03DAD472229EC031000DA6D1 /* Readme.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = Readme.md; sourceTree = \"<group>\"; };\n\t\t03DAD474229EC3CD000DA6D1 /* OfflineMode.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = OfflineMode.md; sourceTree = \"<group>\"; };\n\t\t03DAD475229EC544000DA6D1 /* HardwareDecoding.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = HardwareDecoding.md; sourceTree = \"<group>\"; };\n\t\t03DAD476229EC64D000DA6D1 /* Troubleshooting.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = Troubleshooting.md; sourceTree = \"<group>\"; };\n\t\t03DAD477229ECAAA000DA6D1 /* CustomVideos.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = CustomVideos.md; sourceTree = \"<group>\"; };\n\t\t03DB966D256569F800BFCF20 /* icon-512@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = \"icon-512@2x.png\"; sourceTree = \"<group>\"; };\n\t\t03DB968325657AE600BFCF20 /* LogoIcon-128px@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = \"LogoIcon-128px@2x.png\"; sourceTree = \"<group>\"; };\n\t\t03DC004D248BC5A4005DB0F4 /* Cache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Cache.swift; sourceTree = \"<group>\"; };\n\t\t03E168152673A23900D7442D /* InfoMusicView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfoMusicView.swift; sourceTree = \"<group>\"; };\n\t\t03E168192673A63F00D7442D /* MusicLayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MusicLayer.swift; sourceTree = \"<group>\"; };\n\t\t03E2237024BE048900CD8ED4 /* VideoHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoHeaderView.swift; sourceTree = \"<group>\"; };\n\t\t03E3C1D7256AAAF6000A2A5B /* ru.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = ru.json; sourceTree = \"<group>\"; };\n\t\t03E8730B2165013C002B469B /* DownloadManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownloadManager.swift; sourceTree = \"<group>\"; };\n\t\t03E8730E216501ED002B469B /* AsynchronousOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AsynchronousOperation.swift; sourceTree = \"<group>\"; };\n\t\t03E8731221675FE0002B469B /* TimeManagement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimeManagement.swift; sourceTree = \"<group>\"; };\n\t\t03EBF0BE2746A53B00EC09D1 /* PlayingCollectionViewItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayingCollectionViewItem.swift; sourceTree = \"<group>\"; };\n\t\t03EBF0BF2746A53B00EC09D1 /* PlayingCollectionViewItem.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = PlayingCollectionViewItem.xib; sourceTree = \"<group>\"; };\n\t\t03EED2EE24C44A7900F0C3D4 /* OverlaysViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OverlaysViewController.swift; sourceTree = \"<group>\"; };\n\t\t03EED2EF24C44A7900F0C3D4 /* OverlaysViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = OverlaysViewController.xib; sourceTree = \"<group>\"; };\n\t\t03F3C1B924F2A923007733B5 /* kofi1@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = \"kofi1@2x.png\"; sourceTree = \"<group>\"; };\n\t\t03F5551A24E9C091003AAD0B /* SourceOutlineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SourceOutlineView.swift; sourceTree = \"<group>\"; };\n\t\t03F752CF24EED19B00945B1D /* video_inspire_alabama_montgomery_countryside_00007.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = video_inspire_alabama_montgomery_countryside_00007.png; sourceTree = \"<group>\"; };\n\t\t03F752D024EED19C00945B1D /* video_inspire_california_big-sur_2020_00001.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = \"video_inspire_california_big-sur_2020_00001.png\"; sourceTree = \"<group>\"; };\n\t\t03F752D124EED19C00945B1D /* video_inspire_italy_como_cerano-dintelvi_006.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = \"video_inspire_italy_como_cerano-dintelvi_006.png\"; sourceTree = \"<group>\"; };\n\t\t03F752D224EED19C00945B1D /* video_inspire_california_catalina_00005.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = video_inspire_california_catalina_00005.png; sourceTree = \"<group>\"; };\n\t\t03F752E324EED21100945B1D /* video_inspire_california_vineyard_sierra-mar_sunrise_110.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = \"video_inspire_california_vineyard_sierra-mar_sunrise_110.png\"; sourceTree = \"<group>\"; };\n\t\t03F752E824EEFC3100945B1D /* text.cursor.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = text.cursor.pdf; sourceTree = \"<group>\"; };\n\t\t03F752ED24EEFC8500945B1D /* house.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = house.pdf; sourceTree = \"<group>\"; };\n\t\t03FA49A02423DA1F00863AF6 /* TimerLayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimerLayer.swift; sourceTree = \"<group>\"; };\n\t\t03FA49B32428EE3300863AF6 /* InfoDateView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfoDateView.swift; sourceTree = \"<group>\"; };\n\t\t03FA49B62428F84500863AF6 /* DateLayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateLayer.swift; sourceTree = \"<group>\"; };\n\t\t03FF192F269709AB00A0FA7F /* PlaybackSpeed.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlaybackSpeed.swift; sourceTree = \"<group>\"; };\n\t\tAA7E2E5D1FC62E8B00E5F320 /* AerialPlayerItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AerialPlayerItem.swift; sourceTree = \"<group>\"; };\n\t\tF0058B7E28ABF69B0053699B /* SoundOutputManager+Goodies.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = \"SoundOutputManager+Goodies.swift\"; sourceTree = \"<group>\"; };\n\t\tF0058B7F28ABF69B0053699B /* SoundOutputManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SoundOutputManager.swift; sourceTree = \"<group>\"; };\n\t\tF0058B8028ABF69B0053699B /* Sound.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Sound.swift; sourceTree = \"<group>\"; };\n\t\tF0058B8128ABF69B0053699B /* SoundOutputManager+Properties.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = \"SoundOutputManager+Properties.swift\"; sourceTree = \"<group>\"; };\n\t\tF00864B323AAE7F0003210EF /* DarkMode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DarkMode.swift; sourceTree = \"<group>\"; };\n\t\tF00864B623AAE8E9003210EF /* NightShift.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NightShift.swift; sourceTree = \"<group>\"; };\n\t\tF008DAFC23AADCFB00739DE1 /* Brightness.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Brightness.swift; sourceTree = \"<group>\"; };\n\t\tF05E805328AE8A9C0088B9C5 /* NowPlayingCollectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NowPlayingCollectionView.swift; sourceTree = \"<group>\"; };\n\t\tF06FCF1928DB8673007558BA /* tl.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = tl.json; sourceTree = \"<group>\"; };\n\t\tF07221862AD4354E001F5452 /* CompanionBridge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompanionBridge.swift; sourceTree = \"<group>\"; };\n\t\tF0A3E0A12884683D005E8D8D /* CompanionCacheViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompanionCacheViewController.swift; sourceTree = \"<group>\"; };\n\t\tF0A3E0A22884683D005E8D8D /* CompanionCacheViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = CompanionCacheViewController.xib; sourceTree = \"<group>\"; };\n\t\tFA143CD61BDA3E880041A82B /* AerialApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AerialApp.app; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\tFA143CE51BDA3EEF0041A82B /* AVKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVKit.framework; path = System/Library/Frameworks/AVKit.framework; sourceTree = SDKROOT; };\n\t\tFA36BD3E1BE57F8E00D5E03B /* VideoDownload.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = VideoDownload.swift; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n\t\tFA71996E1D94EC5A00FBC99B /* Aerial Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = \"Aerial Tests.xctest\"; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\tFA7199701D94EC5A00FBC99B /* PreferencesTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesTests.swift; sourceTree = \"<group>\"; };\n\t\tFA7199721D94EC5A00FBC99B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\tFAB22A7D1BE17D7D0065C0F5 /* AssetLoaderDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = AssetLoaderDelegate.swift; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n\t\tFAC36F301BE1756D007F2A20 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = AppDelegate.swift; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n\t\tFAC36F321BE1756D007F2A20 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = \"<group>\"; };\n\t\tFAC36F341BE1756D007F2A20 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = \"<group>\"; };\n\t\tFAC36F351BE1756D007F2A20 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\tFAC36F391BE1756D007F2A20 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\tFAC36F401BE1756D007F2A20 /* AerialVideo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = AerialVideo.swift; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n\t\tFAC36F431BE1756D007F2A20 /* AerialView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = AerialView.swift; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n\t\tFAC36F441BE1756D007F2A20 /* CheckCellView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = CheckCellView.swift; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n\t\tFAC36F661BE1778C007F2A20 /* ManifestLoader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = ManifestLoader.swift; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n\t\tFACAF1A51BD9FC6000E539DC /* Aerial.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Aerial.saver; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\tFAF450201BE2B45D00C1F98A /* VideoLoader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = VideoLoader.swift; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n\t\tFAF450231BE2D2FD00C1F98A /* VideoCache.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = VideoCache.swift; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n/* End PBXFileReference section */\n\n/* Begin PBXFrameworksBuildPhase section */\n\t\t0396D56924B8B7ED00CC021B /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t0396D56A24B8B7ED00CC021B /* CoreLocation.framework in Frameworks */,\n\t\t\t\t0396D56D24B8B7ED00CC021B /* IOKit.framework in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tFA143CD31BDA3E880041A82B /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t03510C772185EF8F008F74F2 /* CoreLocation.framework in Frameworks */,\n\t\t\t\t03510C6B21834EB2008F74F2 /* IOKit.framework in Frameworks */,\n\t\t\t\tFA143CE61BDA3EEF0041A82B /* AVKit.framework in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tFA71996B1D94EC5A00FBC99B /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tFACAF1A11BD9FC6000E539DC /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t03510C732185EF76008F74F2 /* CoreLocation.framework in Frameworks */,\n\t\t\t\t03510C6C21834EFF008F74F2 /* IOKit.framework in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXFrameworksBuildPhase section */\n\n/* Begin PBXGroup section */\n\t\t0300B84624D1FCFE006132E5 /* First time setup */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t0300B84824D1FD24006132E5 /* FirstSetupWindowController.xib */,\n\t\t\t\t0300B84724D1FD24006132E5 /* FirstSetupWindowController.swift */,\n\t\t\t\t0300B86024D2052B006132E5 /* WelcomeViewController.xib */,\n\t\t\t\t0300B85F24D2052B006132E5 /* WelcomeViewController.swift */,\n\t\t\t\t03BF179E24E2F29C0080EF34 /* VideoFormatViewController.xib */,\n\t\t\t\t03BF179D24E2F29C0080EF34 /* VideoFormatViewController.swift */,\n\t\t\t\t03B8742124E41CF8008E3D1B /* CacheSetupViewController.xib */,\n\t\t\t\t03B8742024E41CF8008E3D1B /* CacheSetupViewController.swift */,\n\t\t\t\t037772E024E43AF300D81EEA /* TimeSetupViewController.xib */,\n\t\t\t\t037772DF24E43AF300D81EEA /* TimeSetupViewController.swift */,\n\t\t\t\t037772EC24E44CE100D81EEA /* RecapViewController.xib */,\n\t\t\t\t037772EB24E44CE100D81EEA /* RecapViewController.swift */,\n\t\t\t\t0300B86824D20B12006132E5 /* NextViewController.xib */,\n\t\t\t\t0300B86724D20B12006132E5 /* NextViewController.swift */,\n\t\t\t);\n\t\t\tpath = \"First time setup\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t0306336623A1010800046A59 /* Layers */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t031C5CB6268CA4D100CE35B4 /* Music */,\n\t\t\t\t03A42A9E2449F946003B3012 /* Weather */,\n\t\t\t\t03BF51BB23A2643C008AD373 /* LayerManager.swift */,\n\t\t\t\t0306336A23A142FA00046A59 /* LayerOffsets.swift */,\n\t\t\t\t0345872C2449C52F00C97D1B /* AnimatableLayer.swift */,\n\t\t\t\t034587312449D8EB00C97D1B /* AnimationLayer.swift */,\n\t\t\t\t0306336D23A15FA900046A59 /* AnimationTextLayer.swift */,\n\t\t\t\t030A0F28245C7C7D009E1D97 /* BatteryIconLayer.swift */,\n\t\t\t\t0306336723A1012200046A59 /* LocationLayer.swift */,\n\t\t\t\t03BF51BE23A274CA008AD373 /* MessageLayer.swift */,\n\t\t\t\t03BF51C123A2978B008AD373 /* ClockLayer.swift */,\n\t\t\t\t03FA49B62428F84500863AF6 /* DateLayer.swift */,\n\t\t\t\t036A57D423F30DD00009DC02 /* DownloadIndicatorLayer.swift */,\n\t\t\t\t036A57DA23F5820A0009DC02 /* CountdownLayer.swift */,\n\t\t\t\t03FA49A02423DA1F00863AF6 /* TimerLayer.swift */,\n\t\t\t);\n\t\t\tpath = Layers;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t031945E524CCC44600F37B35 /* Infos panels */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t033811AF24C1E243002E23E0 /* InfoViewController.xib */,\n\t\t\t\t033811AE24C1E243002E23E0 /* InfoViewController.swift */,\n\t\t\t\t031945F224CCC48C00F37B35 /* CreditsViewController.xib */,\n\t\t\t\t031945F124CCC48C00F37B35 /* CreditsViewController.swift */,\n\t\t\t\t031945FA24CCC52600F37B35 /* HelpViewController.xib */,\n\t\t\t\t031945F924CCC52600F37B35 /* HelpViewController.swift */,\n\t\t\t);\n\t\t\tpath = \"Infos panels\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t031C5CB6268CA4D100CE35B4 /* Music */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t03E168192673A63F00D7442D /* MusicLayer.swift */,\n\t\t\t\t031C5CB7268CA4E700CE35B4 /* ArtworkLayer.swift */,\n\t\t\t);\n\t\t\tpath = Music;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t031C5CBB268CBEDC00CE35B4 /* Music */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t0317C19B268B65D10082A40C /* Music.swift */,\n\t\t\t);\n\t\t\tpath = Music;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t033192DF217B77E90073B580 /* Community */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tF06FCF1928DB8673007558BA /* tl.json */,\n\t\t\t\t03977EEF250E6918008FBAFD /* ar.json */,\n\t\t\t\t03977EE7250E6918008FBAFD /* de.json */,\n\t\t\t\t03977EED250E6918008FBAFD /* en.json */,\n\t\t\t\t0350CB78279481F2005F8625 /* hu.json */,\n\t\t\t\t03977EE9250E6918008FBAFD /* es.json */,\n\t\t\t\t03977EE8250E6918008FBAFD /* fr.json */,\n\t\t\t\t03977EEC250E6918008FBAFD /* he.json */,\n\t\t\t\t03977EEB250E6918008FBAFD /* it.json */,\n\t\t\t\t03977EE3250E6917008FBAFD /* ja.json */,\n\t\t\t\t03AA27BC2614A6F800A4D2CF /* ko.json */,\n\t\t\t\t03977EF0250E6918008FBAFD /* nl.json */,\n\t\t\t\t03977EE6250E6917008FBAFD /* pl.json */,\n\t\t\t\t03977EEA250E6918008FBAFD /* pt_BR.json */,\n\t\t\t\t03977EE4250E6917008FBAFD /* pt.json */,\n\t\t\t\t03E3C1D7256AAAF6000A2A5B /* ru.json */,\n\t\t\t\t03977EE2250E6917008FBAFD /* sv.json */,\n\t\t\t\t03977EEE250E6918008FBAFD /* zh_CN.json */,\n\t\t\t\t03977EE5250E6917008FBAFD /* zh_TW.json */,\n\t\t\t\t0369985C2196103300E359D3 /* missingvideos.json */,\n\t\t\t);\n\t\t\tpath = Community;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t0345A23124532DC600DD47CD /* Weather */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t03AA7A4024C84C6200A47970 /* battery.0.pdf */,\n\t\t\t\t03AA7A5924C84C6300A47970 /* bolt.fill.pdf */,\n\t\t\t\t03AA7A5824C84C6300A47970 /* cloud.bolt.pdf */,\n\t\t\t\t03AA7A2524C84C6200A47970 /* cloud.bolt.rain.pdf */,\n\t\t\t\t03AA7A5224C84C6300A47970 /* cloud.drizzle.pdf */,\n\t\t\t\t03AA7A4924C84C6200A47970 /* cloud.fog.pdf */,\n\t\t\t\t03AA7A5124C84C6300A47970 /* cloud.hail.pdf */,\n\t\t\t\t03AA7A3F24C84C6200A47970 /* cloud.heavyrain.pdf */,\n\t\t\t\t03AA7A5724C84C6300A47970 /* cloud.moon.bolt.pdf */,\n\t\t\t\t03AA7A5624C84C6300A47970 /* cloud.moon.pdf */,\n\t\t\t\t03AA7A5024C84C6300A47970 /* cloud.moon.rain.pdf */,\n\t\t\t\t03AA7A4524C84C6200A47970 /* cloud.pdf */,\n\t\t\t\t03AA7A5324C84C6300A47970 /* cloud.rain.pdf */,\n\t\t\t\t03AA7A5B24C84C6300A47970 /* cloud.sleet.pdf */,\n\t\t\t\t03AA7A4F24C84C6300A47970 /* cloud.snow.pdf */,\n\t\t\t\t03AA7A4624C84C6200A47970 /* cloud.sun.bolt.pdf */,\n\t\t\t\t03AA7A5A24C84C6300A47970 /* cloud.sun.pdf */,\n\t\t\t\t03AA7A4224C84C6200A47970 /* cloud.sun.rain.pdf */,\n\t\t\t\t03AA7A4824C84C6200A47970 /* hurricane.pdf */,\n\t\t\t\t03AA7A4C24C84C6300A47970 /* moon.pdf */,\n\t\t\t\t03AA7A3E24C84C6200A47970 /* moon.stars.pdf */,\n\t\t\t\t03AA7A4E24C84C6300A47970 /* smoke.pdf */,\n\t\t\t\t03AA7A3D24C84C6200A47970 /* snow.pdf */,\n\t\t\t\t03AA7A4324C84C6200A47970 /* sun.dust.pdf */,\n\t\t\t\t03AA7A5424C84C6300A47970 /* sun.haze.pdf */,\n\t\t\t\t03AA7A4424C84C6200A47970 /* sun.max.pdf */,\n\t\t\t\t03AA7A4D24C84C6300A47970 /* sun.min.pdf */,\n\t\t\t\t03AA7A4724C84C6200A47970 /* thermometer.snowflake.pdf */,\n\t\t\t\t03AA7A4A24C84C6200A47970 /* thermometer.sun.pdf */,\n\t\t\t\t03AA7A5524C84C6300A47970 /* tornado.pdf */,\n\t\t\t\t03AA7A4B24C84C6200A47970 /* tropicalstorm.pdf */,\n\t\t\t\t03AA7A5C24C84C6300A47970 /* wind.pdf */,\n\t\t\t\t03AA7A3C24C84C6200A47970 /* wind.snow.pdf */,\n\t\t\t\t03AA7A4124C84C6200A47970 /* wrench.pdf */,\n\t\t\t\t03A6D14E25F294C900960135 /* location.north.pdf */,\n\t\t\t);\n\t\t\tpath = Weather;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t0345D01524C0A2F60001045C /* UI Icons */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t03F752ED24EEFC8500945B1D /* house.pdf */,\n\t\t\t\t03F752E824EEFC3100945B1D /* text.cursor.pdf */,\n\t\t\t\t03B8743124E42675008E3D1B /* hand.raised.pdf */,\n\t\t\t\t03B8742F24E42675008E3D1B /* wand.and.rays.pdf */,\n\t\t\t\t03B8743024E42675008E3D1B /* wand.and.stars.pdf */,\n\t\t\t\t0300B7D824D1B533006132E5 /* antenna.radiowaves.left.and.right.pdf */,\n\t\t\t\t0300B7DF24D1B534006132E5 /* arrow.down.circle.fill.pdf */,\n\t\t\t\t0300B7DB24D1B534006132E5 /* arrow.down.circle.pdf */,\n\t\t\t\t0300B7CB24D1B531006132E5 /* bubble.left.and.bubble.right.pdf */,\n\t\t\t\t0300B7E724D1B536006132E5 /* checkmark.circle.fill.pdf */,\n\t\t\t\t0300B7D024D1B532006132E5 /* circle.pdf */,\n\t\t\t\t0300B7D224D1B532006132E5 /* clock.pdf */,\n\t\t\t\t0300B7E624D1B536006132E5 /* dial.pdf */,\n\t\t\t\t0300B7CE24D1B532006132E5 /* eye.pdf */,\n\t\t\t\t0300B7D524D1B533006132E5 /* eye.slash.pdf */,\n\t\t\t\t0300B7D424D1B533006132E5 /* film.pdf */,\n\t\t\t\t0300B7DC24D1B534006132E5 /* flame.pdf */,\n\t\t\t\t0321A53D24D4515B004F1975 /* folder.pdf */,\n\t\t\t\t0300B7CD24D1B532006132E5 /* gear.pdf */,\n\t\t\t\t0300B7CC24D1B531006132E5 /* helm.pdf */,\n\t\t\t\t0300B7D624D1B533006132E5 /* info.circle.pdf */,\n\t\t\t\t0300B7E024D1B535006132E5 /* location.pdf */,\n\t\t\t\t0300B7DE24D1B534006132E5 /* mappin.and.ellipse.pdf */,\n\t\t\t\t0300B7CA24D1B531006132E5 /* person.3.pdf */,\n\t\t\t\t0300B7E424D1B535006132E5 /* regular.cloud.pdf */,\n\t\t\t\t0300B7D724D1B533006132E5 /* regular.moon.stars.pdf */,\n\t\t\t\t0300B7E524D1B535006132E5 /* regular.sun.max.pdf */,\n\t\t\t\t0300B7DD24D1B534006132E5 /* regular.sun.min.pdf */,\n\t\t\t\t030010A524D718D30092AE68 /* slider.horizontal.3.pdf */,\n\t\t\t\t0300B7D324D1B532006132E5 /* sparkles.pdf */,\n\t\t\t\t0300B7E824D1B536006132E5 /* square.and.arrow.down.pdf */,\n\t\t\t\t0300B7E324D1B535006132E5 /* star.fill.pdf */,\n\t\t\t\t0300B7D124D1B532006132E5 /* star.pdf */,\n\t\t\t\t0300B7E224D1B535006132E5 /* sunrise.pdf */,\n\t\t\t\t0300B7D924D1B533006132E5 /* sunset.pdf */,\n\t\t\t\t03075EB024ED794F00FDBE48 /* textformat.alt.pdf */,\n\t\t\t\t03075EA824ED794F00FDBE48 /* trash.pdf */,\n\t\t\t\t0300B7CF24D1B532006132E5 /* text.bubble.pdf */,\n\t\t\t\t0300B7DA24D1B534006132E5 /* tram.fill.pdf */,\n\t\t\t\t0300B7E124D1B535006132E5 /* tv.pdf */,\n\t\t\t\t037772E724E44BB100D81EEA /* xmark.circle.pdf */,\n\t\t\t\t037772F424E4668600D81EEA /* aspectratio.pdf */,\n\t\t\t);\n\t\t\tpath = \"UI Icons\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t0345EDE524C3235900C73038 /* Settings panels */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t03EBF0C62746A54200EC09D1 /* Collection View */,\n\t\t\t\t03298774274687340036D898 /* NowPlayingViewController.xib */,\n\t\t\t\t03298773274687340036D898 /* NowPlayingViewController.swift */,\n\t\t\t\t03933B8A24C3986800A98D94 /* SourcesViewController.xib */,\n\t\t\t\t03933B8924C3986800A98D94 /* SourcesViewController.swift */,\n\t\t\t\t0345EDE724C3239400C73038 /* DisplaysViewController.xib */,\n\t\t\t\t0345EDE624C3239400C73038 /* DisplaysViewController.swift */,\n\t\t\t\t03BDBEA124C467EC00BBD5E9 /* BrightnessViewController.xib */,\n\t\t\t\t03BDBEA024C467EC00BBD5E9 /* BrightnessViewController.swift */,\n\t\t\t\t03BDBEBF24C4727C00BBD5E9 /* TimeViewController.xib */,\n\t\t\t\t03BDBEBE24C4727C00BBD5E9 /* TimeViewController.swift */,\n\t\t\t\t0378985D24C35F8A009B9418 /* CacheViewController.xib */,\n\t\t\t\t0378985C24C35F8A009B9418 /* CacheViewController.swift */,\n\t\t\t\t032E099D24C3897E00387230 /* AdvancedViewController.xib */,\n\t\t\t\t032E099C24C3897E00387230 /* AdvancedViewController.swift */,\n\t\t\t\t03EED2EF24C44A7900F0C3D4 /* OverlaysViewController.xib */,\n\t\t\t\t03EED2EE24C44A7900F0C3D4 /* OverlaysViewController.swift */,\n\t\t\t\t030010AA24D71EB20092AE68 /* FiltersViewController.xib */,\n\t\t\t\t030010A924D71EB20092AE68 /* FiltersViewController.swift */,\n\t\t\t\tF0A3E0A22884683D005E8D8D /* CompanionCacheViewController.xib */,\n\t\t\t\tF0A3E0A12884683D005E8D8D /* CompanionCacheViewController.swift */,\n\t\t\t);\n\t\t\tpath = \"Settings panels\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t0345EDF624C3462100C73038 /* Old stuff */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t03A42A9B2449F601003B3012 /* purple_retina.png */,\n\t\t\t\t03A42A822449F5EA003B3012 /* white_retina.png */,\n\t\t\t\tFAC36F391BE1756D007F2A20 /* Info.plist */,\n\t\t\t\t0395835221807D1F008E8F9C /* thumbnail.png */,\n\t\t\t\t0395835121807D1F008E8F9C /* thumbnail@2x.png */,\n\t\t\t\t0377BF6F24BA15E600C33F9F /* btn_donate.png */,\n\t\t\t\t0313F9E522942AA500B074BB /* CustomVideos.xib */,\n\t\t\t);\n\t\t\tpath = \"Old stuff\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t034A6DAA24ACC7BC00D62129 /* Sources */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t0345D00924BF4E8C0001045C /* Sidebar.swift */,\n\t\t\t\t03C97BA624B5F74900739CED /* VideoList.swift */,\n\t\t\t\t034A6DC124ACC7C800D62129 /* SourceList.swift */,\n\t\t\t\t034A6DC324ACC80200D62129 /* Source.swift */,\n\t\t\t\t03C97BC224B6210500739CED /* SourceInfo.swift */,\n\t\t\t);\n\t\t\tpath = Sources;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t034DEE2B24BF1B8A00A2D3CD /* MainUI */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t0300B84624D1FCFE006132E5 /* First time setup */,\n\t\t\t\t031945E524CCC44600F37B35 /* Infos panels */,\n\t\t\t\t0345EDE524C3235900C73038 /* Settings panels */,\n\t\t\t\t034DEE2D24BF1BC700A2D3CD /* PanelWindowController.xib */,\n\t\t\t\t034DEE2C24BF1BC700A2D3CD /* PanelWindowController.swift */,\n\t\t\t\t0313329B24BF3FA700C84A05 /* SidebarViewController.xib */,\n\t\t\t\t0313329A24BF3FA700C84A05 /* SidebarViewController.swift */,\n\t\t\t\t0345CFEC24BF43280001045C /* VideosViewController.xib */,\n\t\t\t\t0345CFEB24BF43280001045C /* VideosViewController.swift */,\n\t\t\t);\n\t\t\tpath = MainUI;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t034DEE3424BF254F00A2D3CD /* MainUI */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t0345D00D24C07CC70001045C /* VideoCellView.swift */,\n\t\t\t\t03D3A11224C5FC770091FE99 /* AspectFillNSImageView.swift */,\n\t\t\t\t030010A124D706DB0092AE68 /* SidebarOutlineView.swift */,\n\t\t\t\tF05E805328AE8A9C0088B9C5 /* NowPlayingCollectionView.swift */,\n\t\t\t);\n\t\t\tpath = MainUI;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t034F29B523A7A8E1004B34D5 /* PrefPanel */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t030473C924BCA9A40094A1A6 /* VideoViewItem.swift */,\n\t\t\t\t03E2237024BE048900CD8ED4 /* VideoHeaderView.swift */,\n\t\t\t\tFAC36F441BE1756D007F2A20 /* CheckCellView.swift */,\n\t\t\t\t03D1E78622842FB300D10CF7 /* DisplayView.swift */,\n\t\t\t\t034F29B623A7A93D004B34D5 /* InfoTableSource.swift */,\n\t\t\t\t0354D0E823F6C31800D86F9E /* InfoSettingsTableSource.swift */,\n\t\t\t\t038C584623A9304800224630 /* InfoContainerView.swift */,\n\t\t\t\t038C584923A9394000224630 /* InfoCommonView.swift */,\n\t\t\t\t03A596D823AB8F000097EA66 /* InfoLocationView.swift */,\n\t\t\t\t03A596D223AA750F0097EA66 /* InfoMessageView.swift */,\n\t\t\t\t03A596D423AA752F0097EA66 /* InfoClockView.swift */,\n\t\t\t\t038D2EE323B6565900CD91F7 /* InfoBatteryView.swift */,\n\t\t\t\t036A57D723F470940009DC02 /* InfoCountdownView.swift */,\n\t\t\t\t0354D0EB23F6CB7B00D86F9E /* InfoSettingsView.swift */,\n\t\t\t\t030DDA8F2423C3BE0072D5C9 /* InfoTimerView.swift */,\n\t\t\t\t03FA49B32428EE3300863AF6 /* InfoDateView.swift */,\n\t\t\t\t0385FC5C242B9F6E007E6513 /* InfoWeatherView.swift */,\n\t\t\t\t03E168152673A23900D7442D /* InfoMusicView.swift */,\n\t\t\t);\n\t\t\tpath = PrefPanel;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t034F29BA23A7D516004B34D5 /* Prefs */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t034F29BE23A7E28E004B34D5 /* PrefsInfo.swift */,\n\t\t\t\t038D2EDD23B0FB0D00CD91F7 /* PrefsVideos.swift */,\n\t\t\t\t0361B9A723D732A300B6252D /* PrefsDisplays.swift */,\n\t\t\t\t0361B9AA23D73D4500B6252D /* PrefsTime.swift */,\n\t\t\t\t034116D223F9BD3100CD7674 /* PrefsUpdates.swift */,\n\t\t\t\t03A4A80D2451D04C00A1F7A3 /* PrefsAdvanced.swift */,\n\t\t\t\t031FB78A248A87330054BAFD /* PrefsCache.swift */,\n\t\t\t);\n\t\t\tpath = Prefs;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t0385FC57242B9A9B007E6513 /* API */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t0385FC58242B9AE1007E6513 /* APISecrets.swift */,\n\t\t\t\t03A6D14525F109B900960135 /* OpenWeather.swift */,\n\t\t\t\t032851F6260A4C2B00684A81 /* OneCall.swift */,\n\t\t\t\t03AA32612631A8F2002198C3 /* GeoCoding.swift */,\n\t\t\t\t036A7E9A26370C260019186B /* Forecast.swift */,\n\t\t\t);\n\t\t\tpath = API;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t03958347217F43FF008E8F9C /* Time */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t03958348217F4416008E8F9C /* Solar.swift */,\n\t\t\t\t03E8731221675FE0002B469B /* TimeManagement.swift */,\n\t\t\t\t03510C6E21834F38008F74F2 /* IOBridge.m */,\n\t\t\t\t03510C6D21834F38008F74F2 /* Aerial-Bridging-Header.h */,\n\t\t\t);\n\t\t\tpath = Time;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t03A42A9E2449F946003B3012 /* Weather */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t033842E024489D7300A2C523 /* WeatherLayer.swift */,\n\t\t\t\t03A42A9F2449F959003B3012 /* YahooLogoLayer.swift */,\n\t\t\t\t032851FA260A625100684A81 /* ForecastLayer.swift */,\n\t\t\t\t03A42AA2244A0E5F003B3012 /* ConditionLayer.swift */,\n\t\t\t\t033D68802453080C0016F837 /* ConditionSymbolLayer.swift */,\n\t\t\t\t03A6D15225F297CE00960135 /* WindDirectionLayer.swift */,\n\t\t\t);\n\t\t\tpath = Weather;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t03C344FA24B778D500906EA6 /* Sources */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t03F5551A24E9C091003AAD0B /* SourceOutlineView.swift */,\n\t\t\t\t03C344FB24B778EE00906EA6 /* CheckboxCellView.swift */,\n\t\t\t\t03C344FE24B7A22300906EA6 /* DescriptionCellView.swift */,\n\t\t\t\t0321A53224D44E80004F1975 /* ActionCellView.swift */,\n\t\t\t);\n\t\t\tpath = Sources;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t03D1E78D22848F6D00D10CF7 /* Screenshots */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t03F752CF24EED19B00945B1D /* video_inspire_alabama_montgomery_countryside_00007.png */,\n\t\t\t\t03F752D024EED19C00945B1D /* video_inspire_california_big-sur_2020_00001.png */,\n\t\t\t\t03F752D224EED19C00945B1D /* video_inspire_california_catalina_00005.png */,\n\t\t\t\t03F752D124EED19C00945B1D /* video_inspire_italy_como_cerano-dintelvi_006.png */,\n\t\t\t\t03F752E324EED21100945B1D /* video_inspire_california_vineyard_sierra-mar_sunrise_110.png */,\n\t\t\t\t03D1E79022848F7F00D10CF7 /* screen0.jpg */,\n\t\t\t\t03D1E78F22848F7F00D10CF7 /* screen1.jpg */,\n\t\t\t\t03D1E78E22848F7F00D10CF7 /* screen2.jpg */,\n\t\t\t);\n\t\t\tpath = Screenshots;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t03DAD46E229EAC66000DA6D1 /* Documentation */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t03DAD46F229EAC66000DA6D1 /* Installation.md */,\n\t\t\t\t03DAD471229EB1E9000DA6D1 /* ChangeLog.md */,\n\t\t\t\t03DAD474229EC3CD000DA6D1 /* OfflineMode.md */,\n\t\t\t\t03DAD475229EC544000DA6D1 /* HardwareDecoding.md */,\n\t\t\t\t03DAD476229EC64D000DA6D1 /* Troubleshooting.md */,\n\t\t\t\t03DAD477229ECAAA000DA6D1 /* CustomVideos.md */,\n\t\t\t\t030B5E32229FDD26008F2910 /* AutoUpdates.md */,\n\t\t\t\t03D6C78922A0384F00DE830B /* README.md */,\n\t\t\t);\n\t\t\tpath = Documentation;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t03E8730D216501B3002B469B /* Downloads */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t03E8730B2165013C002B469B /* DownloadManager.swift */,\n\t\t\t\t03E8730E216501ED002B469B /* AsynchronousOperation.swift */,\n\t\t\t);\n\t\t\tpath = Downloads;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t03EBF0C62746A54200EC09D1 /* Collection View */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t03EBF0BF2746A53B00EC09D1 /* PlayingCollectionViewItem.xib */,\n\t\t\t\t03EBF0BE2746A53B00EC09D1 /* PlayingCollectionViewItem.swift */,\n\t\t\t);\n\t\t\tpath = \"Collection View\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tF0058B7D28ABF69B0053699B /* ISSoundAdditions */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tF0058B7E28ABF69B0053699B /* SoundOutputManager+Goodies.swift */,\n\t\t\t\tF0058B7F28ABF69B0053699B /* SoundOutputManager.swift */,\n\t\t\t\tF0058B8028ABF69B0053699B /* Sound.swift */,\n\t\t\t\tF0058B8128ABF69B0053699B /* SoundOutputManager+Properties.swift */,\n\t\t\t);\n\t\t\tpath = ISSoundAdditions;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tF008DAFB23AADC8E00739DE1 /* Hardware */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tF0058B7D28ABF69B0053699B /* ISSoundAdditions */,\n\t\t\t\t03D1E7892284471A00D10CF7 /* DisplayDetection.swift */,\n\t\t\t\t03608A2B22A56465008F08A2 /* HardwareDetection.swift */,\n\t\t\t\t032D1160239A7D82007E7756 /* Battery.swift */,\n\t\t\t\tF008DAFC23AADCFB00739DE1 /* Brightness.swift */,\n\t\t\t\tF00864B323AAE7F0003210EF /* DarkMode.swift */,\n\t\t\t\tF00864B623AAE8E9003210EF /* NightShift.swift */,\n\t\t\t);\n\t\t\tpath = Hardware;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tFA2D7AA01BDD849E009EA54C /* Frameworks */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t03510C722185EF76008F74F2 /* CoreLocation.framework */,\n\t\t\t\t03510C6A21834EB2008F74F2 /* IOKit.framework */,\n\t\t\t\tFA143CE51BDA3EEF0041A82B /* AVKit.framework */,\n\t\t\t);\n\t\t\tname = Frameworks;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tFA71996F1D94EC5A00FBC99B /* Tests */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tFA7199701D94EC5A00FBC99B /* PreferencesTests.swift */,\n\t\t\t\tFA7199721D94EC5A00FBC99B /* Info.plist */,\n\t\t\t);\n\t\t\tpath = Tests;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tFAC36F2F1BE1756D007F2A20 /* App */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tFAC36F301BE1756D007F2A20 /* AppDelegate.swift */,\n\t\t\t\tFAC36F311BE1756D007F2A20 /* Resources */,\n\t\t\t);\n\t\t\tname = App;\n\t\t\tpath = Aerial/App;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tFAC36F311BE1756D007F2A20 /* Resources */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tFAC36F321BE1756D007F2A20 /* Assets.xcassets */,\n\t\t\t\tFAC36F331BE1756D007F2A20 /* MainMenu.xib */,\n\t\t\t\tFAC36F351BE1756D007F2A20 /* Info.plist */,\n\t\t\t);\n\t\t\tpath = Resources;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tFAC36F361BE1756D007F2A20 /* Resources */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t03F3C1B924F2A923007733B5 /* kofi1@2x.png */,\n\t\t\t\t03DB968325657AE600BFCF20 /* LogoIcon-128px@2x.png */,\n\t\t\t\t03DB966D256569F800BFCF20 /* icon-512@2x.png */,\n\t\t\t\t0319460824D1A09F00F37B35 /* icon-320@2x.png */,\n\t\t\t\t0343E9F82630590A00AC702F /* openweather_logo.png */,\n\t\t\t\t0345EDF624C3462100C73038 /* Old stuff */,\n\t\t\t\t0345D01524C0A2F60001045C /* UI Icons */,\n\t\t\t\t034DEE2B24BF1B8A00A2D3CD /* MainUI */,\n\t\t\t\t0345A23124532DC600DD47CD /* Weather */,\n\t\t\t\t03D1E78D22848F6D00D10CF7 /* Screenshots */,\n\t\t\t\t033192DF217B77E90073B580 /* Community */,\n\t\t\t);\n\t\t\tpath = Resources;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tFAC36F3C1BE1756D007F2A20 /* Source */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tFAC36F3D1BE1756D007F2A20 /* Controllers */,\n\t\t\t\tFAC36F3F1BE1756D007F2A20 /* Models */,\n\t\t\t\tFAC36F421BE1756D007F2A20 /* Views */,\n\t\t\t);\n\t\t\tname = Source;\n\t\t\tpath = Aerial/Source;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tFAC36F3D1BE1756D007F2A20 /* Controllers */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t0313F9E722942B4500B074BB /* CustomVideoController.swift */,\n\t\t\t);\n\t\t\tpath = Controllers;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tFAC36F3F1BE1756D007F2A20 /* Models */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t034A6DAA24ACC7BC00D62129 /* Sources */,\n\t\t\t\t0385FC57242B9A9B007E6513 /* API */,\n\t\t\t\tF008DAFB23AADC8E00739DE1 /* Hardware */,\n\t\t\t\t034F29BA23A7D516004B34D5 /* Prefs */,\n\t\t\t\t03958347217F43FF008E8F9C /* Time */,\n\t\t\t\t03E8730D216501B3002B469B /* Downloads */,\n\t\t\t\tFAC36F411BE1756D007F2A20 /* Cache */,\n\t\t\t\tFAC36F621BE17701007F2A20 /* Extensions */,\n\t\t\t\t031C5CBB268CBEDC00CE35B4 /* Music */,\n\t\t\t\t0338119424C1D15B002E23E0 /* Aerial.swift */,\n\t\t\t\tFAC36F401BE1756D007F2A20 /* AerialVideo.swift */,\n\t\t\t\t0374C9FD247AC5BC002F29D3 /* Locations.swift */,\n\t\t\t\tFAC36F661BE1778C007F2A20 /* ManifestLoader.swift */,\n\t\t\t\t03893CB2217749F0008E7125 /* ErrorLog.swift */,\n\t\t\t\t0313F9EB2294468600B074BB /* SeededGenerator.swift */,\n\t\t\t\t0313F9EE22955F3B00B074BB /* CustomVideoFolders.swift */,\n\t\t\t\t03AD45FE22981B0C00261325 /* CustomVideoFolders+helpers.swift */,\n\t\t\t\t03C97BBF24B60E2F00739CED /* FileHelpers.swift */,\n\t\t\t\t03FF192F269709AB00A0FA7F /* PlaybackSpeed.swift */,\n\t\t\t\tF07221862AD4354E001F5452 /* CompanionBridge.swift */,\n\t\t\t);\n\t\t\tpath = Models;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tFAC36F411BE1756D007F2A20 /* Cache */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tFAB22A7D1BE17D7D0065C0F5 /* AssetLoaderDelegate.swift */,\n\t\t\t\tFAF450201BE2B45D00C1F98A /* VideoLoader.swift */,\n\t\t\t\tFAF450231BE2D2FD00C1F98A /* VideoCache.swift */,\n\t\t\t\tFA36BD3E1BE57F8E00D5E03B /* VideoDownload.swift */,\n\t\t\t\t03A2CB9B216BA9AF0061E8E8 /* VideoManager.swift */,\n\t\t\t\t03233B67217272640077D3F9 /* PoiStringProvider.swift */,\n\t\t\t\t03DC004D248BC5A4005DB0F4 /* Cache.swift */,\n\t\t\t\t03D3A10C24C5D7CC0091FE99 /* Thumbnails.swift */,\n\t\t\t\t03977F1F250E7165008FBAFD /* TimeMachine.swift */,\n\t\t\t);\n\t\t\tpath = Cache;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tFAC36F421BE1756D007F2A20 /* Views */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t034DEE3424BF254F00A2D3CD /* MainUI */,\n\t\t\t\t03C344FA24B778D500906EA6 /* Sources */,\n\t\t\t\t034F29B523A7A8E1004B34D5 /* PrefPanel */,\n\t\t\t\t0306336623A1010800046A59 /* Layers */,\n\t\t\t\tFAC36F431BE1756D007F2A20 /* AerialView.swift */,\n\t\t\t\t032D1163239A7F0C007E7756 /* AerialView+Brightness.swift */,\n\t\t\t\t035D524E239AA31A00DC29DC /* AerialView+Player.swift */,\n\t\t\t\tAA7E2E5D1FC62E8B00E5F320 /* AerialPlayerItem.swift */,\n\t\t\t);\n\t\t\tpath = Views;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tFAC36F621BE17701007F2A20 /* Extensions */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t039385792175D4B80040B850 /* AVPlayerViewExtension.swift */,\n\t\t\t\t03A4A80A2451CE2C00A1F7A3 /* NSImage+trim.swift */,\n\t\t\t\t03047A5324D2DD8E000EFE62 /* NSMenuItem+icons.swift */,\n\t\t\t\t0321A54324D5C863004F1975 /* NSButton+icons.swift */,\n\t\t\t\t0300109624D6EF4C0092AE68 /* AVPlayerItem+vibrance.swift */,\n\t\t\t\t0332076C26D7C355001F9837 /* AVAsset+VideoOrientation.swift */,\n\t\t\t\t03C605DB277B45CA005CA51F /* DispatchQueue+Extension.swift */,\n\t\t\t);\n\t\t\tpath = Extensions;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tFACAF19B1BD9FC6000E539DC = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t03DAD472229EC031000DA6D1 /* Readme.md */,\n\t\t\t\t03DAD46E229EAC66000DA6D1 /* Documentation */,\n\t\t\t\tFAC36F2F1BE1756D007F2A20 /* App */,\n\t\t\t\tFAC36F361BE1756D007F2A20 /* Resources */,\n\t\t\t\tFAC36F3C1BE1756D007F2A20 /* Source */,\n\t\t\t\tFA71996F1D94EC5A00FBC99B /* Tests */,\n\t\t\t\tFA2D7AA01BDD849E009EA54C /* Frameworks */,\n\t\t\t\tFACAF1A61BD9FC6000E539DC /* Products */,\n\t\t\t\t0396D50624B8B7D700CC021B /* AerialApp copy-Info.plist */,\n\t\t\t\t0396D5B624B8B7EE00CC021B /* Aerial copy-Info.plist */,\n\t\t\t);\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tFACAF1A61BD9FC6000E539DC /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tFACAF1A51BD9FC6000E539DC /* Aerial.saver */,\n\t\t\t\tFA143CD61BDA3E880041A82B /* AerialApp.app */,\n\t\t\t\tFA71996E1D94EC5A00FBC99B /* Aerial Tests.xctest */,\n\t\t\t\t0396D5B524B8B7ED00CC021B /* Aerial (low dependencies).saver */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXGroup section */\n\n/* Begin PBXHeadersBuildPhase section */\n\t\t0396D56E24B8B7ED00CC021B /* Headers */ = {\n\t\t\tisa = PBXHeadersBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t0396D56F24B8B7ED00CC021B /* Aerial-Bridging-Header.h in Headers */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tFACAF1A21BD9FC6000E539DC /* Headers */ = {\n\t\t\tisa = PBXHeadersBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t03510C7021834FC3008F74F2 /* Aerial-Bridging-Header.h in Headers */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXHeadersBuildPhase section */\n\n/* Begin PBXNativeTarget section */\n\t\t0396D50724B8B7ED00CC021B /* Aerial (low dependencies) */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 0396D5B224B8B7ED00CC021B /* Build configuration list for PBXNativeTarget \"Aerial (low dependencies)\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t0396D50824B8B7ED00CC021B /* Run Script - Swiftlint */,\n\t\t\t\t0396D50924B8B7ED00CC021B /* Sources */,\n\t\t\t\t0396D56924B8B7ED00CC021B /* Frameworks */,\n\t\t\t\t0396D56E24B8B7ED00CC021B /* Headers */,\n\t\t\t\t0396D57024B8B7ED00CC021B /* Resources */,\n\t\t\t\t0396D5AE24B8B7ED00CC021B /* Embed Frameworks */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = \"Aerial (low dependencies)\";\n\t\t\tpackageProductDependencies = (\n\t\t\t);\n\t\t\tproductName = Aerial;\n\t\t\tproductReference = 0396D5B524B8B7ED00CC021B /* Aerial (low dependencies).saver */;\n\t\t\tproductType = \"com.apple.product-type.bundle\";\n\t\t};\n\t\tFA143CD51BDA3E880041A82B /* AerialApp */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = FA143CE01BDA3E880041A82B /* Build configuration list for PBXNativeTarget \"AerialApp\" */;\n\t\t\tbuildPhases = (\n\t\t\t\tFA74B8481D94DCE0004FE056 /* Run Script - Swiftlint */,\n\t\t\t\tFA143CD21BDA3E880041A82B /* Sources */,\n\t\t\t\tFA143CD31BDA3E880041A82B /* Frameworks */,\n\t\t\t\tFA143CD41BDA3E880041A82B /* Resources */,\n\t\t\t\t034116D123F9AD0600CD7674 /* Embed Frameworks */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = AerialApp;\n\t\t\tpackageProductDependencies = (\n\t\t\t);\n\t\t\tproductName = \"Aerial Test\";\n\t\t\tproductReference = FA143CD61BDA3E880041A82B /* AerialApp.app */;\n\t\t\tproductType = \"com.apple.product-type.application\";\n\t\t};\n\t\tFA71996D1D94EC5A00FBC99B /* Aerial Tests */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = FA7199751D94EC5A00FBC99B /* Build configuration list for PBXNativeTarget \"Aerial Tests\" */;\n\t\t\tbuildPhases = (\n\t\t\t\tFA71996A1D94EC5A00FBC99B /* Sources */,\n\t\t\t\tFA71996B1D94EC5A00FBC99B /* Frameworks */,\n\t\t\t\tFA71996C1D94EC5A00FBC99B /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\tFA7199741D94EC5A00FBC99B /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = \"Aerial Tests\";\n\t\t\tproductName = \"Aerial Tests\";\n\t\t\tproductReference = FA71996E1D94EC5A00FBC99B /* Aerial Tests.xctest */;\n\t\t\tproductType = \"com.apple.product-type.bundle.unit-test\";\n\t\t};\n\t\tFACAF1A41BD9FC6000E539DC /* Aerial */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = FACAF1AF1BD9FC6000E539DC /* Build configuration list for PBXNativeTarget \"Aerial\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t7E9B50FB2187D302002895ED /* Run Script - Swiftlint */,\n\t\t\t\tFACAF1A01BD9FC6000E539DC /* Sources */,\n\t\t\t\tFACAF1A11BD9FC6000E539DC /* Frameworks */,\n\t\t\t\tFACAF1A21BD9FC6000E539DC /* Headers */,\n\t\t\t\tFACAF1A31BD9FC6000E539DC /* Resources */,\n\t\t\t\t034116CE23F9AD0100CD7674 /* Embed Frameworks */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = Aerial;\n\t\t\tpackageProductDependencies = (\n\t\t\t);\n\t\t\tproductName = Aerial;\n\t\t\tproductReference = FACAF1A51BD9FC6000E539DC /* Aerial.saver */;\n\t\t\tproductType = \"com.apple.product-type.bundle\";\n\t\t};\n/* End PBXNativeTarget section */\n\n/* Begin PBXProject section */\n\t\tFACAF19C1BD9FC6000E539DC /* Project object */ = {\n\t\t\tisa = PBXProject;\n\t\t\tattributes = {\n\t\t\t\tLastSwiftUpdateCheck = 0800;\n\t\t\t\tLastUpgradeCheck = 1010;\n\t\t\t\tORGANIZATIONNAME = \"Guillaume Louel\";\n\t\t\t\tTargetAttributes = {\n\t\t\t\t\t0396D50724B8B7ED00CC021B = {\n\t\t\t\t\t\tDevelopmentTeam = 3L54M5L5KK;\n\t\t\t\t\t\tProvisioningStyle = Manual;\n\t\t\t\t\t};\n\t\t\t\t\tFA143CD51BDA3E880041A82B = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 7.0;\n\t\t\t\t\t\tDevelopmentTeam = 3L54M5L5KK;\n\t\t\t\t\t\tLastSwiftMigration = 1020;\n\t\t\t\t\t\tProvisioningStyle = Automatic;\n\t\t\t\t\t};\n\t\t\t\t\tFA71996D1D94EC5A00FBC99B = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 8.0;\n\t\t\t\t\t\tLastSwiftMigration = 1020;\n\t\t\t\t\t\tProvisioningStyle = Automatic;\n\t\t\t\t\t\tTestTargetID = FA143CD51BDA3E880041A82B;\n\t\t\t\t\t};\n\t\t\t\t\tFACAF1A41BD9FC6000E539DC = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 7.0;\n\t\t\t\t\t\tDevelopmentTeam = 3L54M5L5KK;\n\t\t\t\t\t\tLastSwiftMigration = 1020;\n\t\t\t\t\t\tProvisioningStyle = Manual;\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t\tbuildConfigurationList = FACAF19F1BD9FC6000E539DC /* Build configuration list for PBXProject \"Aerial\" */;\n\t\t\tcompatibilityVersion = \"Xcode 3.2\";\n\t\t\tdevelopmentRegion = en;\n\t\t\thasScannedForEncodings = 0;\n\t\t\tknownRegions = (\n\t\t\t\ten,\n\t\t\t\tBase,\n\t\t\t);\n\t\t\tmainGroup = FACAF19B1BD9FC6000E539DC;\n\t\t\tpackageReferences = (\n\t\t\t);\n\t\t\tproductRefGroup = FACAF1A61BD9FC6000E539DC /* Products */;\n\t\t\tprojectDirPath = \"\";\n\t\t\tprojectRoot = \"\";\n\t\t\ttargets = (\n\t\t\t\tFACAF1A41BD9FC6000E539DC /* Aerial */,\n\t\t\t\t0396D50724B8B7ED00CC021B /* Aerial (low dependencies) */,\n\t\t\t\tFA143CD51BDA3E880041A82B /* AerialApp */,\n\t\t\t\tFA71996D1D94EC5A00FBC99B /* Aerial Tests */,\n\t\t\t);\n\t\t};\n/* End PBXProject section */\n\n/* Begin PBXResourcesBuildPhase section */\n\t\t0396D57024B8B7ED00CC021B /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t03977F19250E6918008FBAFD /* ar.json in Resources */,\n\t\t\t\t03AA7A9424C84C6300A47970 /* sun.min.pdf in Resources */,\n\t\t\t\t03AA7A7F24C84C6300A47970 /* cloud.sun.bolt.pdf in Resources */,\n\t\t\t\t03977F0D250E6918008FBAFD /* it.json in Resources */,\n\t\t\t\t03AA7AB524C84C6400A47970 /* cloud.bolt.pdf in Resources */,\n\t\t\t\t03AA7A7C24C84C6300A47970 /* cloud.pdf in Resources */,\n\t\t\t\t0300B83524D1B536006132E5 /* star.fill.pdf in Resources */,\n\t\t\t\t03977F0A250E6918008FBAFD /* pt_BR.json in Resources */,\n\t\t\t\t0300B86D24D20B12006132E5 /* NextViewController.xib in Resources */,\n\t\t\t\t03298779274687340036D898 /* NowPlayingViewController.xib in Resources */,\n\t\t\t\t0345CFF124BF43280001045C /* VideosViewController.xib in Resources */,\n\t\t\t\t0300B81D24D1B536006132E5 /* arrow.down.circle.pdf in Resources */,\n\t\t\t\t0300B81724D1B536006132E5 /* sunset.pdf in Resources */,\n\t\t\t\t03F752EF24EEFC8500945B1D /* house.pdf in Resources */,\n\t\t\t\t0300B7F924D1B536006132E5 /* text.bubble.pdf in Resources */,\n\t\t\t\t032E09A224C3897E00387230 /* AdvancedViewController.xib in Resources */,\n\t\t\t\t0300B82324D1B536006132E5 /* regular.sun.min.pdf in Resources */,\n\t\t\t\t0321A53F24D4515B004F1975 /* folder.pdf in Resources */,\n\t\t\t\t0300B82924D1B536006132E5 /* arrow.down.circle.fill.pdf in Resources */,\n\t\t\t\tF06FCF1B28DB8673007558BA /* tl.json in Resources */,\n\t\t\t\t037772F124E44CE100D81EEA /* RecapViewController.xib in Resources */,\n\t\t\t\t03977F10250E6918008FBAFD /* he.json in Resources */,\n\t\t\t\t0396D57624B8B7ED00CC021B /* white_retina.png in Resources */,\n\t\t\t\t037772FD24E4668600D81EEA /* aspectratio.pdf in Resources */,\n\t\t\t\t03AA7A8224C84C6300A47970 /* thermometer.snowflake.pdf in Resources */,\n\t\t\t\t03AA27BE2614A6F800A4D2CF /* ko.json in Resources */,\n\t\t\t\t03DB968525657AE600BFCF20 /* LogoIcon-128px@2x.png in Resources */,\n\t\t\t\t03AA7A7024C84C6300A47970 /* wrench.pdf in Resources */,\n\t\t\t\t03AA7A9124C84C6300A47970 /* moon.pdf in Resources */,\n\t\t\t\t0300B81124D1B536006132E5 /* regular.moon.stars.pdf in Resources */,\n\t\t\t\t03AA7AA624C84C6300A47970 /* cloud.rain.pdf in Resources */,\n\t\t\t\t03F752E024EED19C00945B1D /* video_inspire_california_catalina_00005.png in Resources */,\n\t\t\t\t03AA7A9724C84C6300A47970 /* smoke.pdf in Resources */,\n\t\t\t\t03AA7A8824C84C6300A47970 /* cloud.fog.pdf in Resources */,\n\t\t\t\t030010A724D718D30092AE68 /* slider.horizontal.3.pdf in Resources */,\n\t\t\t\t0300B82C24D1B536006132E5 /* location.pdf in Resources */,\n\t\t\t\t0300B84D24D1FD24006132E5 /* FirstSetupWindowController.xib in Resources */,\n\t\t\t\t03977F07250E6918008FBAFD /* es.json in Resources */,\n\t\t\t\t03AA7A6D24C84C6300A47970 /* battery.0.pdf in Resources */,\n\t\t\t\t03977F01250E6918008FBAFD /* de.json in Resources */,\n\t\t\t\t0300B82624D1B536006132E5 /* mappin.and.ellipse.pdf in Resources */,\n\t\t\t\t0300B80B24D1B536006132E5 /* eye.slash.pdf in Resources */,\n\t\t\t\t0350CB7D279481F2005F8625 /* hu.json in Resources */,\n\t\t\t\t0396D57924B8B7ED00CC021B /* screen2.jpg in Resources */,\n\t\t\t\t03B8743324E42675008E3D1B /* wand.and.rays.pdf in Resources */,\n\t\t\t\t0319461124D1A09F00F37B35 /* icon-320@2x.png in Resources */,\n\t\t\t\t03AA7ABE24C84C6400A47970 /* cloud.sleet.pdf in Resources */,\n\t\t\t\t03977EFB250E6918008FBAFD /* zh_TW.json in Resources */,\n\t\t\t\t03BDBEC424C4727C00BBD5E9 /* TimeViewController.xib in Resources */,\n\t\t\t\t03AA7A8B24C84C6300A47970 /* thermometer.sun.pdf in Resources */,\n\t\t\t\t0300B83E24D1B536006132E5 /* dial.pdf in Resources */,\n\t\t\t\t0300B83224D1B536006132E5 /* sunrise.pdf in Resources */,\n\t\t\t\t03F752E524EED21100945B1D /* video_inspire_california_vineyard_sierra-mar_sunrise_110.png in Resources */,\n\t\t\t\t0300B80824D1B536006132E5 /* film.pdf in Resources */,\n\t\t\t\t0300B83B24D1B536006132E5 /* regular.sun.max.pdf in Resources */,\n\t\t\t\t0300B7FF24D1B536006132E5 /* star.pdf in Resources */,\n\t\t\t\t03AA7A7624C84C6300A47970 /* sun.dust.pdf in Resources */,\n\t\t\t\t03B8742624E41CF8008E3D1B /* CacheSetupViewController.xib in Resources */,\n\t\t\t\t0377BF8724BA15E700C33F9F /* btn_donate.png in Resources */,\n\t\t\t\t037772E524E43AF300D81EEA /* TimeSetupViewController.xib in Resources */,\n\t\t\t\t037772E924E44BB100D81EEA /* xmark.circle.pdf in Resources */,\n\t\t\t\t0300B82F24D1B536006132E5 /* tv.pdf in Resources */,\n\t\t\t\t03977EF8250E6918008FBAFD /* pt.json in Resources */,\n\t\t\t\t0300B81424D1B536006132E5 /* antenna.radiowaves.left.and.right.pdf in Resources */,\n\t\t\t\t03075EB224ED794F00FDBE48 /* trash.pdf in Resources */,\n\t\t\t\t03AA7ABB24C84C6400A47970 /* cloud.sun.pdf in Resources */,\n\t\t\t\t0396D58B24B8B7ED00CC021B /* screen0.jpg in Resources */,\n\t\t\t\t0300B7F624D1B536006132E5 /* eye.pdf in Resources */,\n\t\t\t\t03AA7AB824C84C6400A47970 /* bolt.fill.pdf in Resources */,\n\t\t\t\t03AA7A9D24C84C6300A47970 /* cloud.moon.rain.pdf in Resources */,\n\t\t\t\t0378986224C35F8A009B9418 /* CacheViewController.xib in Resources */,\n\t\t\t\t03F3C1BB24F2A923007733B5 /* kofi1@2x.png in Resources */,\n\t\t\t\t03977EF2250E6918008FBAFD /* sv.json in Resources */,\n\t\t\t\t03977F16250E6918008FBAFD /* zh_CN.json in Resources */,\n\t\t\t\t030010AF24D71EB20092AE68 /* FiltersViewController.xib in Resources */,\n\t\t\t\t03AA7A7324C84C6300A47970 /* cloud.sun.rain.pdf in Resources */,\n\t\t\t\t03977EF5250E6918008FBAFD /* ja.json in Resources */,\n\t\t\t\t0396D58D24B8B7ED00CC021B /* thumbnail@2x.png in Resources */,\n\t\t\t\t0396D58E24B8B7ED00CC021B /* thumbnail.png in Resources */,\n\t\t\t\t03F752D824EED19C00945B1D /* video_inspire_california_big-sur_2020_00001.png in Resources */,\n\t\t\t\t0300B86524D2052B006132E5 /* WelcomeViewController.xib in Resources */,\n\t\t\t\t03AA7A6A24C84C6300A47970 /* cloud.heavyrain.pdf in Resources */,\n\t\t\t\t03AA7A9A24C84C6300A47970 /* cloud.snow.pdf in Resources */,\n\t\t\t\t0300B80224D1B536006132E5 /* clock.pdf in Resources */,\n\t\t\t\t0300B81A24D1B536006132E5 /* tram.fill.pdf in Resources */,\n\t\t\t\t0300B82024D1B536006132E5 /* flame.pdf in Resources */,\n\t\t\t\t03977EFE250E6918008FBAFD /* pl.json in Resources */,\n\t\t\t\t03B8743924E42675008E3D1B /* hand.raised.pdf in Resources */,\n\t\t\t\t03AA7AA924C84C6300A47970 /* sun.haze.pdf in Resources */,\n\t\t\t\t0300B7EA24D1B536006132E5 /* person.3.pdf in Resources */,\n\t\t\t\t03F752DC24EED19C00945B1D /* video_inspire_italy_como_cerano-dintelvi_006.png in Resources */,\n\t\t\t\t031332A024BF3FA700C84A05 /* SidebarViewController.xib in Resources */,\n\t\t\t\t031945FF24CCC52600F37B35 /* HelpViewController.xib in Resources */,\n\t\t\t\t0300B7F024D1B536006132E5 /* helm.pdf in Resources */,\n\t\t\t\t03AA7A8E24C84C6300A47970 /* tropicalstorm.pdf in Resources */,\n\t\t\t\t0345EDEC24C3239400C73038 /* DisplaysViewController.xib in Resources */,\n\t\t\t\t0396D59224B8B7ED00CC021B /* screen1.jpg in Resources */,\n\t\t\t\t03977F1C250E6918008FBAFD /* nl.json in Resources */,\n\t\t\t\t0300B7ED24D1B536006132E5 /* bubble.left.and.bubble.right.pdf in Resources */,\n\t\t\t\t03AA7AA324C84C6300A47970 /* cloud.drizzle.pdf in Resources */,\n\t\t\t\t03977F04250E6918008FBAFD /* fr.json in Resources */,\n\t\t\t\t03AA7AB224C84C6400A47970 /* cloud.moon.bolt.pdf in Resources */,\n\t\t\t\t0300B7FC24D1B536006132E5 /* circle.pdf in Resources */,\n\t\t\t\t0300B80524D1B536006132E5 /* sparkles.pdf in Resources */,\n\t\t\t\t03E3C1DF256AAAF6000A2A5B /* ru.json in Resources */,\n\t\t\t\t03B8743624E42675008E3D1B /* wand.and.stars.pdf in Resources */,\n\t\t\t\t03BDBEA624C467EC00BBD5E9 /* BrightnessViewController.xib in Resources */,\n\t\t\t\t03AA7AC124C84C6400A47970 /* wind.pdf in Resources */,\n\t\t\t\t0396D59D24B8B7ED00CC021B /* missingvideos.json in Resources */,\n\t\t\t\t034DEE3224BF1BC700A2D3CD /* PanelWindowController.xib in Resources */,\n\t\t\t\t03AA7AAC24C84C6300A47970 /* tornado.pdf in Resources */,\n\t\t\t\t0300B7F324D1B536006132E5 /* gear.pdf in Resources */,\n\t\t\t\t03AA7A5E24C84C6300A47970 /* cloud.bolt.rain.pdf in Resources */,\n\t\t\t\t0300B83824D1B536006132E5 /* regular.cloud.pdf in Resources */,\n\t\t\t\t03AA7A8524C84C6300A47970 /* hurricane.pdf in Resources */,\n\t\t\t\t0343E9FA2630590A00AC702F /* openweather_logo.png in Resources */,\n\t\t\t\t0300B80E24D1B536006132E5 /* info.circle.pdf in Resources */,\n\t\t\t\t03AA7A6424C84C6300A47970 /* snow.pdf in Resources */,\n\t\t\t\t0396D5A824B8B7ED00CC021B /* CustomVideos.xib in Resources */,\n\t\t\t\t03AA7AA024C84C6300A47970 /* cloud.hail.pdf in Resources */,\n\t\t\t\t03BF17A324E2F29C0080EF34 /* VideoFormatViewController.xib in Resources */,\n\t\t\t\t03F752D424EED19C00945B1D /* video_inspire_alabama_montgomery_countryside_00007.png in Resources */,\n\t\t\t\t03DB9675256569F800BFCF20 /* icon-512@2x.png in Resources */,\n\t\t\t\t03EED2F424C44A7900F0C3D4 /* OverlaysViewController.xib in Resources */,\n\t\t\t\t0300B84124D1B536006132E5 /* checkmark.circle.fill.pdf in Resources */,\n\t\t\t\t031945F724CCC48C00F37B35 /* CreditsViewController.xib in Resources */,\n\t\t\t\t03075EB524ED794F00FDBE48 /* textformat.alt.pdf in Resources */,\n\t\t\t\t03AA7AAF24C84C6400A47970 /* cloud.moon.pdf in Resources */,\n\t\t\t\t0396D5AB24B8B7ED00CC021B /* purple_retina.png in Resources */,\n\t\t\t\t03AA7A6124C84C6300A47970 /* wind.snow.pdf in Resources */,\n\t\t\t\t03977F13250E6918008FBAFD /* en.json in Resources */,\n\t\t\t\t03EBF0C42746A53B00EC09D1 /* PlayingCollectionViewItem.xib in Resources */,\n\t\t\t\t03AA7A6724C84C6300A47970 /* moon.stars.pdf in Resources */,\n\t\t\t\t0300B84424D1B536006132E5 /* square.and.arrow.down.pdf in Resources */,\n\t\t\t\tF0A3E0A72884683D005E8D8D /* CompanionCacheViewController.xib in Resources */,\n\t\t\t\t03AA7A7924C84C6300A47970 /* sun.max.pdf in Resources */,\n\t\t\t\t03933B8F24C3986800A98D94 /* SourcesViewController.xib in Resources */,\n\t\t\t\t03F752EA24EEFC3100945B1D /* text.cursor.pdf in Resources */,\n\t\t\t\t03A6D15025F294C900960135 /* location.north.pdf in Resources */,\n\t\t\t\t033811B424C1E243002E23E0 /* InfoViewController.xib in Resources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tFA143CD41BDA3E880041A82B /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t03977F0E250E6918008FBAFD /* it.json in Resources */,\n\t\t\t\t0300B7F724D1B536006132E5 /* eye.pdf in Resources */,\n\t\t\t\t03BDBEC524C4727C00BBD5E9 /* TimeViewController.xib in Resources */,\n\t\t\t\t0300B80024D1B536006132E5 /* star.pdf in Resources */,\n\t\t\t\t03977EFC250E6918008FBAFD /* zh_TW.json in Resources */,\n\t\t\t\t03DAD470229EAC66000DA6D1 /* Installation.md in Resources */,\n\t\t\t\t03AA7A6B24C84C6300A47970 /* cloud.heavyrain.pdf in Resources */,\n\t\t\t\t033811B524C1E243002E23E0 /* InfoViewController.xib in Resources */,\n\t\t\t\t03A42A9D2449F602003B3012 /* purple_retina.png in Resources */,\n\t\t\t\t03AA7A7D24C84C6300A47970 /* cloud.pdf in Resources */,\n\t\t\t\t037772F224E44CE100D81EEA /* RecapViewController.xib in Resources */,\n\t\t\t\t03977F08250E6918008FBAFD /* es.json in Resources */,\n\t\t\t\t03F752EB24EEFC3100945B1D /* text.cursor.pdf in Resources */,\n\t\t\t\t03977F14250E6918008FBAFD /* en.json in Resources */,\n\t\t\t\t0300B81E24D1B536006132E5 /* arrow.down.circle.pdf in Resources */,\n\t\t\t\tF06FCF1C28DB8673007558BA /* tl.json in Resources */,\n\t\t\t\t0300B82724D1B536006132E5 /* mappin.and.ellipse.pdf in Resources */,\n\t\t\t\t0300B7EB24D1B536006132E5 /* person.3.pdf in Resources */,\n\t\t\t\t0343E9FB2630590A00AC702F /* openweather_logo.png in Resources */,\n\t\t\t\t03AA7AB024C84C6400A47970 /* cloud.moon.pdf in Resources */,\n\t\t\t\t0300B81524D1B536006132E5 /* antenna.radiowaves.left.and.right.pdf in Resources */,\n\t\t\t\t03D1E79522848F7F00D10CF7 /* screen1.jpg in Resources */,\n\t\t\t\t0300B80C24D1B536006132E5 /* eye.slash.pdf in Resources */,\n\t\t\t\t03AA7AA124C84C6300A47970 /* cloud.hail.pdf in Resources */,\n\t\t\t\t0345EDED24C3239400C73038 /* DisplaysViewController.xib in Resources */,\n\t\t\t\t03AA7A7424C84C6300A47970 /* cloud.sun.rain.pdf in Resources */,\n\t\t\t\t03AA7AC224C84C6400A47970 /* wind.pdf in Resources */,\n\t\t\t\t03AA7A8F24C84C6300A47970 /* tropicalstorm.pdf in Resources */,\n\t\t\t\t03AA7A6824C84C6300A47970 /* moon.stars.pdf in Resources */,\n\t\t\t\t03B8743A24E42675008E3D1B /* hand.raised.pdf in Resources */,\n\t\t\t\t03AA7A8324C84C6300A47970 /* thermometer.snowflake.pdf in Resources */,\n\t\t\t\t0300B81824D1B536006132E5 /* sunset.pdf in Resources */,\n\t\t\t\t03977F1A250E6918008FBAFD /* ar.json in Resources */,\n\t\t\t\t03AA7A7124C84C6300A47970 /* wrench.pdf in Resources */,\n\t\t\t\t0369985E2196129C00E359D3 /* missingvideos.json in Resources */,\n\t\t\t\t0300B83024D1B536006132E5 /* tv.pdf in Resources */,\n\t\t\t\t03AA7A9824C84C6300A47970 /* smoke.pdf in Resources */,\n\t\t\t\t0300B84E24D1FD24006132E5 /* FirstSetupWindowController.xib in Resources */,\n\t\t\t\t0319461224D1A09F00F37B35 /* icon-320@2x.png in Resources */,\n\t\t\t\t03AA7ABF24C84C6400A47970 /* cloud.sleet.pdf in Resources */,\n\t\t\t\t03977F11250E6918008FBAFD /* he.json in Resources */,\n\t\t\t\t031945F824CCC48C00F37B35 /* CreditsViewController.xib in Resources */,\n\t\t\t\t03933B9024C3986800A98D94 /* SourcesViewController.xib in Resources */,\n\t\t\t\t0300B82D24D1B536006132E5 /* location.pdf in Resources */,\n\t\t\t\t037772EA24E44BB100D81EEA /* xmark.circle.pdf in Resources */,\n\t\t\t\tF0A3E0A82884683D005E8D8D /* CompanionCacheViewController.xib in Resources */,\n\t\t\t\t0300B83624D1B536006132E5 /* star.fill.pdf in Resources */,\n\t\t\t\t03977EFF250E6918008FBAFD /* pl.json in Resources */,\n\t\t\t\t03AA7A9B24C84C6300A47970 /* cloud.snow.pdf in Resources */,\n\t\t\t\t0395835621807D1F008E8F9C /* thumbnail.png in Resources */,\n\t\t\t\t0300B84224D1B536006132E5 /* checkmark.circle.fill.pdf in Resources */,\n\t\t\t\t0300B83F24D1B536006132E5 /* dial.pdf in Resources */,\n\t\t\t\t03E3C1E0256AAAF6000A2A5B /* ru.json in Resources */,\n\t\t\t\t0313F9E92294337F00B074BB /* CustomVideos.xib in Resources */,\n\t\t\t\t03977F05250E6918008FBAFD /* fr.json in Resources */,\n\t\t\t\t0378986324C35F8A009B9418 /* CacheViewController.xib in Resources */,\n\t\t\t\t0321A54024D4515B004F1975 /* folder.pdf in Resources */,\n\t\t\t\t03977F1D250E6918008FBAFD /* nl.json in Resources */,\n\t\t\t\t0300B7F124D1B536006132E5 /* helm.pdf in Resources */,\n\t\t\t\t037772FE24E4668600D81EEA /* aspectratio.pdf in Resources */,\n\t\t\t\t03AA27BF2614A6F800A4D2CF /* ko.json in Resources */,\n\t\t\t\t0300B80F24D1B536006132E5 /* info.circle.pdf in Resources */,\n\t\t\t\t03977EF3250E6918008FBAFD /* sv.json in Resources */,\n\t\t\t\t03AA7A6E24C84C6300A47970 /* battery.0.pdf in Resources */,\n\t\t\t\t0300B7F424D1B536006132E5 /* gear.pdf in Resources */,\n\t\t\t\t0319460024CCC52600F37B35 /* HelpViewController.xib in Resources */,\n\t\t\t\t03AA7AAA24C84C6300A47970 /* sun.haze.pdf in Resources */,\n\t\t\t\t03977F17250E6918008FBAFD /* zh_CN.json in Resources */,\n\t\t\t\t03AA7A9224C84C6300A47970 /* moon.pdf in Resources */,\n\t\t\t\t03B8743724E42675008E3D1B /* wand.and.stars.pdf in Resources */,\n\t\t\t\t0300B83924D1B536006132E5 /* regular.cloud.pdf in Resources */,\n\t\t\t\t034DEE3324BF1BC700A2D3CD /* PanelWindowController.xib in Resources */,\n\t\t\t\t03DB9676256569F800BFCF20 /* icon-512@2x.png in Resources */,\n\t\t\t\t0300B84524D1B536006132E5 /* square.and.arrow.down.pdf in Resources */,\n\t\t\t\t03AA7A8924C84C6300A47970 /* cloud.fog.pdf in Resources */,\n\t\t\t\t03AA7A8024C84C6300A47970 /* cloud.sun.bolt.pdf in Resources */,\n\t\t\t\t0300B83324D1B536006132E5 /* sunrise.pdf in Resources */,\n\t\t\t\tFAC36F481BE1756D007F2A20 /* Assets.xcassets in Resources */,\n\t\t\t\t03AA7AAD24C84C6300A47970 /* tornado.pdf in Resources */,\n\t\t\t\t03DAD473229EC031000DA6D1 /* Readme.md in Resources */,\n\t\t\t\t0300B83C24D1B536006132E5 /* regular.sun.max.pdf in Resources */,\n\t\t\t\t030010A824D718D30092AE68 /* slider.horizontal.3.pdf in Resources */,\n\t\t\t\t03AA7A8624C84C6300A47970 /* hurricane.pdf in Resources */,\n\t\t\t\t03F752F024EEFC8500945B1D /* house.pdf in Resources */,\n\t\t\t\t0300B80924D1B536006132E5 /* film.pdf in Resources */,\n\t\t\t\t0329877A274687340036D898 /* NowPlayingViewController.xib in Resources */,\n\t\t\t\t03977F0B250E6918008FBAFD /* pt_BR.json in Resources */,\n\t\t\t\t0300B80324D1B536006132E5 /* clock.pdf in Resources */,\n\t\t\t\t03F3C1BC24F2A923007733B5 /* kofi1@2x.png in Resources */,\n\t\t\t\t031332A124BF3FA700C84A05 /* SidebarViewController.xib in Resources */,\n\t\t\t\t03AA7A7724C84C6300A47970 /* sun.dust.pdf in Resources */,\n\t\t\t\t0350CB7E279481F2005F8625 /* hu.json in Resources */,\n\t\t\t\t0300B86E24D20B12006132E5 /* NextViewController.xib in Resources */,\n\t\t\t\t03AA7AB924C84C6400A47970 /* bolt.fill.pdf in Resources */,\n\t\t\t\t03F752DD24EED19C00945B1D /* video_inspire_italy_como_cerano-dintelvi_006.png in Resources */,\n\t\t\t\t03D1E79222848F7F00D10CF7 /* screen2.jpg in Resources */,\n\t\t\t\t03B8743424E42675008E3D1B /* wand.and.rays.pdf in Resources */,\n\t\t\t\tFAC36F4A1BE1756D007F2A20 /* MainMenu.xib in Resources */,\n\t\t\t\t0300B81224D1B536006132E5 /* regular.moon.stars.pdf in Resources */,\n\t\t\t\t03DB968625657AE600BFCF20 /* LogoIcon-128px@2x.png in Resources */,\n\t\t\t\t030010B024D71EB20092AE68 /* FiltersViewController.xib in Resources */,\n\t\t\t\t0377BF8824BA15E700C33F9F /* btn_donate.png in Resources */,\n\t\t\t\t0300B7FD24D1B536006132E5 /* circle.pdf in Resources */,\n\t\t\t\t03BF17A424E2F29C0080EF34 /* VideoFormatViewController.xib in Resources */,\n\t\t\t\t0300B7FA24D1B536006132E5 /* text.bubble.pdf in Resources */,\n\t\t\t\t03EBF0C52746A53B00EC09D1 /* PlayingCollectionViewItem.xib in Resources */,\n\t\t\t\t03977EF9250E6918008FBAFD /* pt.json in Resources */,\n\t\t\t\t03AA7A6224C84C6300A47970 /* wind.snow.pdf in Resources */,\n\t\t\t\t03EED2F524C44A7900F0C3D4 /* OverlaysViewController.xib in Resources */,\n\t\t\t\t0300B82424D1B536006132E5 /* regular.sun.min.pdf in Resources */,\n\t\t\t\t0300B81B24D1B536006132E5 /* tram.fill.pdf in Resources */,\n\t\t\t\t03AA7AB324C84C6400A47970 /* cloud.moon.bolt.pdf in Resources */,\n\t\t\t\t0300B80624D1B536006132E5 /* sparkles.pdf in Resources */,\n\t\t\t\t03075EB624ED794F00FDBE48 /* textformat.alt.pdf in Resources */,\n\t\t\t\t03F752D924EED19C00945B1D /* video_inspire_california_big-sur_2020_00001.png in Resources */,\n\t\t\t\t0300B82A24D1B536006132E5 /* arrow.down.circle.fill.pdf in Resources */,\n\t\t\t\t03F752E624EED21100945B1D /* video_inspire_california_vineyard_sierra-mar_sunrise_110.png in Resources */,\n\t\t\t\t03AA7A5F24C84C6300A47970 /* cloud.bolt.rain.pdf in Resources */,\n\t\t\t\t03AA7A7A24C84C6300A47970 /* sun.max.pdf in Resources */,\n\t\t\t\t03A6D15125F294C900960135 /* location.north.pdf in Resources */,\n\t\t\t\t0300B7EE24D1B536006132E5 /* bubble.left.and.bubble.right.pdf in Resources */,\n\t\t\t\t03AA7A8C24C84C6300A47970 /* thermometer.sun.pdf in Resources */,\n\t\t\t\t03977F02250E6918008FBAFD /* de.json in Resources */,\n\t\t\t\t03AA7AA724C84C6300A47970 /* cloud.rain.pdf in Resources */,\n\t\t\t\t03B8742724E41CF8008E3D1B /* CacheSetupViewController.xib in Resources */,\n\t\t\t\t03AA7A9E24C84C6300A47970 /* cloud.moon.rain.pdf in Resources */,\n\t\t\t\t03AA7ABC24C84C6400A47970 /* cloud.sun.pdf in Resources */,\n\t\t\t\t03977EF6250E6918008FBAFD /* ja.json in Resources */,\n\t\t\t\t0395835421807D1F008E8F9C /* thumbnail@2x.png in Resources */,\n\t\t\t\t03AA7A6524C84C6300A47970 /* snow.pdf in Resources */,\n\t\t\t\t0300B86624D2052B006132E5 /* WelcomeViewController.xib in Resources */,\n\t\t\t\t03A42A9A2449F5EA003B3012 /* white_retina.png in Resources */,\n\t\t\t\t0345CFF224BF43280001045C /* VideosViewController.xib in Resources */,\n\t\t\t\t032E09A324C3897E00387230 /* AdvancedViewController.xib in Resources */,\n\t\t\t\t03F752D524EED19C00945B1D /* video_inspire_alabama_montgomery_countryside_00007.png in Resources */,\n\t\t\t\t03AA7AA424C84C6300A47970 /* cloud.drizzle.pdf in Resources */,\n\t\t\t\t03F752E124EED19C00945B1D /* video_inspire_california_catalina_00005.png in Resources */,\n\t\t\t\t03075EB324ED794F00FDBE48 /* trash.pdf in Resources */,\n\t\t\t\t03BDBEA724C467EC00BBD5E9 /* BrightnessViewController.xib in Resources */,\n\t\t\t\t03AA7AB624C84C6400A47970 /* cloud.bolt.pdf in Resources */,\n\t\t\t\t03D1E79822848F7F00D10CF7 /* screen0.jpg in Resources */,\n\t\t\t\t0300B82124D1B536006132E5 /* flame.pdf in Resources */,\n\t\t\t\t037772E624E43AF300D81EEA /* TimeSetupViewController.xib in Resources */,\n\t\t\t\t03AA7A9524C84C6300A47970 /* sun.min.pdf in Resources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tFA71996C1D94EC5A00FBC99B /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t03F752DA24EED19C00945B1D /* video_inspire_california_big-sur_2020_00001.png in Resources */,\n\t\t\t\t03D1E79322848F7F00D10CF7 /* screen2.jpg in Resources */,\n\t\t\t\t03F752E724EED21100945B1D /* video_inspire_california_vineyard_sierra-mar_sunrise_110.png in Resources */,\n\t\t\t\t03F752D624EED19C00945B1D /* video_inspire_alabama_montgomery_countryside_00007.png in Resources */,\n\t\t\t\t03F752E224EED19C00945B1D /* video_inspire_california_catalina_00005.png in Resources */,\n\t\t\t\t03D1E79622848F7F00D10CF7 /* screen1.jpg in Resources */,\n\t\t\t\t03F752DE24EED19C00945B1D /* video_inspire_italy_como_cerano-dintelvi_006.png in Resources */,\n\t\t\t\t03F752EC24EEFC3100945B1D /* text.cursor.pdf in Resources */,\n\t\t\t\t03D1E79922848F7F00D10CF7 /* screen0.jpg in Resources */,\n\t\t\t\t03F752F124EEFC8500945B1D /* house.pdf in Resources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tFACAF1A31BD9FC6000E539DC /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t03977F18250E6918008FBAFD /* ar.json in Resources */,\n\t\t\t\t03AA7A9324C84C6300A47970 /* sun.min.pdf in Resources */,\n\t\t\t\t03AA7A7E24C84C6300A47970 /* cloud.sun.bolt.pdf in Resources */,\n\t\t\t\t03977F0C250E6918008FBAFD /* it.json in Resources */,\n\t\t\t\t03AA7AB424C84C6400A47970 /* cloud.bolt.pdf in Resources */,\n\t\t\t\t03AA7A7B24C84C6300A47970 /* cloud.pdf in Resources */,\n\t\t\t\t0300B83424D1B536006132E5 /* star.fill.pdf in Resources */,\n\t\t\t\t03977F09250E6918008FBAFD /* pt_BR.json in Resources */,\n\t\t\t\t0300B86C24D20B12006132E5 /* NextViewController.xib in Resources */,\n\t\t\t\t03298778274687340036D898 /* NowPlayingViewController.xib in Resources */,\n\t\t\t\t0345CFF024BF43280001045C /* VideosViewController.xib in Resources */,\n\t\t\t\t0300B81C24D1B536006132E5 /* arrow.down.circle.pdf in Resources */,\n\t\t\t\t0300B81624D1B536006132E5 /* sunset.pdf in Resources */,\n\t\t\t\t03F752EE24EEFC8500945B1D /* house.pdf in Resources */,\n\t\t\t\t0300B7F824D1B536006132E5 /* text.bubble.pdf in Resources */,\n\t\t\t\t032E09A124C3897E00387230 /* AdvancedViewController.xib in Resources */,\n\t\t\t\t0300B82224D1B536006132E5 /* regular.sun.min.pdf in Resources */,\n\t\t\t\t0321A53E24D4515B004F1975 /* folder.pdf in Resources */,\n\t\t\t\t0300B82824D1B536006132E5 /* arrow.down.circle.fill.pdf in Resources */,\n\t\t\t\tF06FCF1A28DB8673007558BA /* tl.json in Resources */,\n\t\t\t\t037772F024E44CE100D81EEA /* RecapViewController.xib in Resources */,\n\t\t\t\t03977F0F250E6918008FBAFD /* he.json in Resources */,\n\t\t\t\t03A42A992449F5EA003B3012 /* white_retina.png in Resources */,\n\t\t\t\t037772FC24E4668600D81EEA /* aspectratio.pdf in Resources */,\n\t\t\t\t03AA7A8124C84C6300A47970 /* thermometer.snowflake.pdf in Resources */,\n\t\t\t\t03AA27BD2614A6F800A4D2CF /* ko.json in Resources */,\n\t\t\t\t03DB968425657AE600BFCF20 /* LogoIcon-128px@2x.png in Resources */,\n\t\t\t\t03AA7A6F24C84C6300A47970 /* wrench.pdf in Resources */,\n\t\t\t\t03AA7A9024C84C6300A47970 /* moon.pdf in Resources */,\n\t\t\t\t0300B81024D1B536006132E5 /* regular.moon.stars.pdf in Resources */,\n\t\t\t\t03AA7AA524C84C6300A47970 /* cloud.rain.pdf in Resources */,\n\t\t\t\t03F752DF24EED19C00945B1D /* video_inspire_california_catalina_00005.png in Resources */,\n\t\t\t\t03AA7A9624C84C6300A47970 /* smoke.pdf in Resources */,\n\t\t\t\t03AA7A8724C84C6300A47970 /* cloud.fog.pdf in Resources */,\n\t\t\t\t030010A624D718D30092AE68 /* slider.horizontal.3.pdf in Resources */,\n\t\t\t\t0300B82B24D1B536006132E5 /* location.pdf in Resources */,\n\t\t\t\t0300B84C24D1FD24006132E5 /* FirstSetupWindowController.xib in Resources */,\n\t\t\t\t03977F06250E6918008FBAFD /* es.json in Resources */,\n\t\t\t\t03AA7A6C24C84C6300A47970 /* battery.0.pdf in Resources */,\n\t\t\t\t03977F00250E6918008FBAFD /* de.json in Resources */,\n\t\t\t\t0300B82524D1B536006132E5 /* mappin.and.ellipse.pdf in Resources */,\n\t\t\t\t0300B80A24D1B536006132E5 /* eye.slash.pdf in Resources */,\n\t\t\t\t0350CB7C279481F2005F8625 /* hu.json in Resources */,\n\t\t\t\t03D1E79122848F7F00D10CF7 /* screen2.jpg in Resources */,\n\t\t\t\t03B8743224E42675008E3D1B /* wand.and.rays.pdf in Resources */,\n\t\t\t\t0319461024D1A09F00F37B35 /* icon-320@2x.png in Resources */,\n\t\t\t\t03AA7ABD24C84C6400A47970 /* cloud.sleet.pdf in Resources */,\n\t\t\t\t03977EFA250E6918008FBAFD /* zh_TW.json in Resources */,\n\t\t\t\t03BDBEC324C4727C00BBD5E9 /* TimeViewController.xib in Resources */,\n\t\t\t\t03AA7A8A24C84C6300A47970 /* thermometer.sun.pdf in Resources */,\n\t\t\t\t0300B83D24D1B536006132E5 /* dial.pdf in Resources */,\n\t\t\t\t0300B83124D1B536006132E5 /* sunrise.pdf in Resources */,\n\t\t\t\t03F752E424EED21100945B1D /* video_inspire_california_vineyard_sierra-mar_sunrise_110.png in Resources */,\n\t\t\t\t0300B80724D1B536006132E5 /* film.pdf in Resources */,\n\t\t\t\t0300B83A24D1B536006132E5 /* regular.sun.max.pdf in Resources */,\n\t\t\t\t0300B7FE24D1B536006132E5 /* star.pdf in Resources */,\n\t\t\t\t03AA7A7524C84C6300A47970 /* sun.dust.pdf in Resources */,\n\t\t\t\t03B8742524E41CF8008E3D1B /* CacheSetupViewController.xib in Resources */,\n\t\t\t\t0377BF8624BA15E700C33F9F /* btn_donate.png in Resources */,\n\t\t\t\t037772E424E43AF300D81EEA /* TimeSetupViewController.xib in Resources */,\n\t\t\t\t037772E824E44BB100D81EEA /* xmark.circle.pdf in Resources */,\n\t\t\t\t0300B82E24D1B536006132E5 /* tv.pdf in Resources */,\n\t\t\t\t03977EF7250E6918008FBAFD /* pt.json in Resources */,\n\t\t\t\t0300B81324D1B536006132E5 /* antenna.radiowaves.left.and.right.pdf in Resources */,\n\t\t\t\t03075EB124ED794F00FDBE48 /* trash.pdf in Resources */,\n\t\t\t\t03AA7ABA24C84C6400A47970 /* cloud.sun.pdf in Resources */,\n\t\t\t\t03D1E79722848F7F00D10CF7 /* screen0.jpg in Resources */,\n\t\t\t\t0300B7F524D1B536006132E5 /* eye.pdf in Resources */,\n\t\t\t\t03AA7AB724C84C6400A47970 /* bolt.fill.pdf in Resources */,\n\t\t\t\t03AA7A9C24C84C6300A47970 /* cloud.moon.rain.pdf in Resources */,\n\t\t\t\t0378986124C35F8A009B9418 /* CacheViewController.xib in Resources */,\n\t\t\t\t03F3C1BA24F2A923007733B5 /* kofi1@2x.png in Resources */,\n\t\t\t\t03977EF1250E6918008FBAFD /* sv.json in Resources */,\n\t\t\t\t03977F15250E6918008FBAFD /* zh_CN.json in Resources */,\n\t\t\t\t030010AE24D71EB20092AE68 /* FiltersViewController.xib in Resources */,\n\t\t\t\t03AA7A7224C84C6300A47970 /* cloud.sun.rain.pdf in Resources */,\n\t\t\t\t03977EF4250E6918008FBAFD /* ja.json in Resources */,\n\t\t\t\t0395835321807D1F008E8F9C /* thumbnail@2x.png in Resources */,\n\t\t\t\t0395835521807D1F008E8F9C /* thumbnail.png in Resources */,\n\t\t\t\t03F752D724EED19C00945B1D /* video_inspire_california_big-sur_2020_00001.png in Resources */,\n\t\t\t\t0300B86424D2052B006132E5 /* WelcomeViewController.xib in Resources */,\n\t\t\t\t03AA7A6924C84C6300A47970 /* cloud.heavyrain.pdf in Resources */,\n\t\t\t\t03AA7A9924C84C6300A47970 /* cloud.snow.pdf in Resources */,\n\t\t\t\t0300B80124D1B536006132E5 /* clock.pdf in Resources */,\n\t\t\t\t0300B81924D1B536006132E5 /* tram.fill.pdf in Resources */,\n\t\t\t\t0300B81F24D1B536006132E5 /* flame.pdf in Resources */,\n\t\t\t\t03977EFD250E6918008FBAFD /* pl.json in Resources */,\n\t\t\t\t03B8743824E42675008E3D1B /* hand.raised.pdf in Resources */,\n\t\t\t\t03AA7AA824C84C6300A47970 /* sun.haze.pdf in Resources */,\n\t\t\t\t0300B7E924D1B536006132E5 /* person.3.pdf in Resources */,\n\t\t\t\t03F752DB24EED19C00945B1D /* video_inspire_italy_como_cerano-dintelvi_006.png in Resources */,\n\t\t\t\t0313329F24BF3FA700C84A05 /* SidebarViewController.xib in Resources */,\n\t\t\t\t031945FE24CCC52600F37B35 /* HelpViewController.xib in Resources */,\n\t\t\t\t0300B7EF24D1B536006132E5 /* helm.pdf in Resources */,\n\t\t\t\t03AA7A8D24C84C6300A47970 /* tropicalstorm.pdf in Resources */,\n\t\t\t\t0345EDEB24C3239400C73038 /* DisplaysViewController.xib in Resources */,\n\t\t\t\t03D1E79422848F7F00D10CF7 /* screen1.jpg in Resources */,\n\t\t\t\t03977F1B250E6918008FBAFD /* nl.json in Resources */,\n\t\t\t\t0300B7EC24D1B536006132E5 /* bubble.left.and.bubble.right.pdf in Resources */,\n\t\t\t\t03AA7AA224C84C6300A47970 /* cloud.drizzle.pdf in Resources */,\n\t\t\t\t03977F03250E6918008FBAFD /* fr.json in Resources */,\n\t\t\t\t03AA7AB124C84C6400A47970 /* cloud.moon.bolt.pdf in Resources */,\n\t\t\t\t0300B7FB24D1B536006132E5 /* circle.pdf in Resources */,\n\t\t\t\t0300B80424D1B536006132E5 /* sparkles.pdf in Resources */,\n\t\t\t\t03E3C1DE256AAAF6000A2A5B /* ru.json in Resources */,\n\t\t\t\t03B8743524E42675008E3D1B /* wand.and.stars.pdf in Resources */,\n\t\t\t\t03BDBEA524C467EC00BBD5E9 /* BrightnessViewController.xib in Resources */,\n\t\t\t\t03AA7AC024C84C6400A47970 /* wind.pdf in Resources */,\n\t\t\t\t0369985D2196103300E359D3 /* missingvideos.json in Resources */,\n\t\t\t\t034DEE3124BF1BC700A2D3CD /* PanelWindowController.xib in Resources */,\n\t\t\t\t03AA7AAB24C84C6300A47970 /* tornado.pdf in Resources */,\n\t\t\t\t0300B7F224D1B536006132E5 /* gear.pdf in Resources */,\n\t\t\t\t03AA7A5D24C84C6300A47970 /* cloud.bolt.rain.pdf in Resources */,\n\t\t\t\t0300B83724D1B536006132E5 /* regular.cloud.pdf in Resources */,\n\t\t\t\t03AA7A8424C84C6300A47970 /* hurricane.pdf in Resources */,\n\t\t\t\t0343E9F92630590A00AC702F /* openweather_logo.png in Resources */,\n\t\t\t\t0300B80D24D1B536006132E5 /* info.circle.pdf in Resources */,\n\t\t\t\t03AA7A6324C84C6300A47970 /* snow.pdf in Resources */,\n\t\t\t\t0313F9E622942AA500B074BB /* CustomVideos.xib in Resources */,\n\t\t\t\t03AA7A9F24C84C6300A47970 /* cloud.hail.pdf in Resources */,\n\t\t\t\t03BF17A224E2F29C0080EF34 /* VideoFormatViewController.xib in Resources */,\n\t\t\t\t03F752D324EED19C00945B1D /* video_inspire_alabama_montgomery_countryside_00007.png in Resources */,\n\t\t\t\t03DB9674256569F800BFCF20 /* icon-512@2x.png in Resources */,\n\t\t\t\t03EED2F324C44A7900F0C3D4 /* OverlaysViewController.xib in Resources */,\n\t\t\t\t0300B84024D1B536006132E5 /* checkmark.circle.fill.pdf in Resources */,\n\t\t\t\t031945F624CCC48C00F37B35 /* CreditsViewController.xib in Resources */,\n\t\t\t\t03075EB424ED794F00FDBE48 /* textformat.alt.pdf in Resources */,\n\t\t\t\t03AA7AAE24C84C6300A47970 /* cloud.moon.pdf in Resources */,\n\t\t\t\t03A42A9C2449F602003B3012 /* purple_retina.png in Resources */,\n\t\t\t\t03AA7A6024C84C6300A47970 /* wind.snow.pdf in Resources */,\n\t\t\t\t03977F12250E6918008FBAFD /* en.json in Resources */,\n\t\t\t\t03EBF0C32746A53B00EC09D1 /* PlayingCollectionViewItem.xib in Resources */,\n\t\t\t\t03AA7A6624C84C6300A47970 /* moon.stars.pdf in Resources */,\n\t\t\t\t0300B84324D1B536006132E5 /* square.and.arrow.down.pdf in Resources */,\n\t\t\t\tF0A3E0A62884683D005E8D8D /* CompanionCacheViewController.xib in Resources */,\n\t\t\t\t03AA7A7824C84C6300A47970 /* sun.max.pdf in Resources */,\n\t\t\t\t03933B8E24C3986800A98D94 /* SourcesViewController.xib in Resources */,\n\t\t\t\t03F752E924EEFC3100945B1D /* text.cursor.pdf in Resources */,\n\t\t\t\t03A6D14F25F294C900960135 /* location.north.pdf in Resources */,\n\t\t\t\t033811B324C1E243002E23E0 /* InfoViewController.xib in Resources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXResourcesBuildPhase section */\n\n/* Begin PBXShellScriptBuildPhase section */\n\t\t0396D50824B8B7ED00CC021B /* Run Script - Swiftlint */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t);\n\t\t\tname = \"Run Script - Swiftlint\";\n\t\t\toutputPaths = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"#if which swiftlint >/dev/null; then\\n#    if [ -z \\\"$CI\\\" ]; then\\n#        make --directory=${SRCROOT} xcode-lint\\n#    fi\\n#else\\n#    echo \\\"warning: SwiftLint not installed, install using `brew install swiftlint`\\\"\\n#fi\\nif which swiftlint >/dev/null; then\\n    swiftlint autocorrect\\nelse\\n    echo \\\"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\\\"\\nfi\\n\";\n\t\t};\n\t\t7E9B50FB2187D302002895ED /* Run Script - Swiftlint */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t);\n\t\t\tname = \"Run Script - Swiftlint\";\n\t\t\toutputPaths = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"#if which swiftlint >/dev/null; then\\n#    if [ -z \\\"$CI\\\" ]; then\\n#        make --directory=${SRCROOT} xcode-lint\\n#    fi\\n#else\\n#    echo \\\"warning: SwiftLint not installed, install using `brew install swiftlint`\\\"\\n#fi\\n#if which swiftlint >/dev/null; then\\n#    swiftlint autocorrect\\n#else\\n#    echo \\\"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\\\"\\n#fi\\n\";\n\t\t};\n\t\tFA74B8481D94DCE0004FE056 /* Run Script - Swiftlint */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t);\n\t\t\tname = \"Run Script - Swiftlint\";\n\t\t\toutputPaths = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"#if which swiftlint >/dev/null; then\\n#    if [ -z \\\"$CI\\\" ]; then\\n#        make --directory=${SRCROOT} xcode-lint\\n#    fi\\n#else\\n#    echo \\\"warning: SwiftLint not installed, install using `brew install swiftlint`\\\"\\n#fi\\n#if which swiftlint >/dev/null; then\\n#    swiftlint autocorrect\\n#    swiftlint\\n#else\\n#    echo \\\"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\\\"\\n#fi\\n\";\n\t\t};\n/* End PBXShellScriptBuildPhase section */\n\n/* Begin PBXSourcesBuildPhase section */\n\t\t0396D50924B8B7ED00CC021B /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t0396D50B24B8B7ED00CC021B /* DisplayDetection.swift in Sources */,\n\t\t\t\tF07221882AD4354E001F5452 /* CompanionBridge.swift in Sources */,\n\t\t\t\t0396D50C24B8B7ED00CC021B /* LayerOffsets.swift in Sources */,\n\t\t\t\t0396D50D24B8B7ED00CC021B /* APISecrets.swift in Sources */,\n\t\t\t\t0396D50E24B8B7ED00CC021B /* NightShift.swift in Sources */,\n\t\t\t\t0396D51024B8B7ED00CC021B /* CheckCellView.swift in Sources */,\n\t\t\t\t0396D51124B8B7ED00CC021B /* PrefsUpdates.swift in Sources */,\n\t\t\t\t0300B86224D2052B006132E5 /* WelcomeViewController.swift in Sources */,\n\t\t\t\t03D3A10E24C5D7CC0091FE99 /* Thumbnails.swift in Sources */,\n\t\t\t\t0396D51224B8B7ED00CC021B /* AerialView.swift in Sources */,\n\t\t\t\t03BF17A024E2F29C0080EF34 /* VideoFormatViewController.swift in Sources */,\n\t\t\t\t032851FC260A625100684A81 /* ForecastLayer.swift in Sources */,\n\t\t\t\t0396D51324B8B7ED00CC021B /* PrefsCache.swift in Sources */,\n\t\t\t\t0396D51424B8B7ED00CC021B /* AVPlayerViewExtension.swift in Sources */,\n\t\t\t\t0396D51524B8B7ED00CC021B /* AsynchronousOperation.swift in Sources */,\n\t\t\t\t0396D51624B8B7ED00CC021B /* LayerManager.swift in Sources */,\n\t\t\t\t0396D51824B8B7ED00CC021B /* IOBridge.m in Sources */,\n\t\t\t\t0396D51924B8B7ED00CC021B /* DarkMode.swift in Sources */,\n\t\t\t\t03047A5524D2DD8E000EFE62 /* NSMenuItem+icons.swift in Sources */,\n\t\t\t\t0300109824D6EF4C0092AE68 /* AVPlayerItem+vibrance.swift in Sources */,\n\t\t\t\t0396D51A24B8B7ED00CC021B /* CustomVideoFolders.swift in Sources */,\n\t\t\t\t036A7E9C26370C260019186B /* Forecast.swift in Sources */,\n\t\t\t\t0396D51B24B8B7ED00CC021B /* InfoTimerView.swift in Sources */,\n\t\t\t\t0396D51D24B8B7ED00CC021B /* MessageLayer.swift in Sources */,\n\t\t\t\t0396D51E24B8B7ED00CC021B /* InfoCommonView.swift in Sources */,\n\t\t\t\t031945FC24CCC52600F37B35 /* HelpViewController.swift in Sources */,\n\t\t\t\t0396D51F24B8B7ED00CC021B /* AerialView+Brightness.swift in Sources */,\n\t\t\t\t03D3A11424C5FC770091FE99 /* AspectFillNSImageView.swift in Sources */,\n\t\t\t\tF0058B8C28ABF69B0053699B /* SoundOutputManager+Properties.swift in Sources */,\n\t\t\t\t030473CC24BCA9A40094A1A6 /* VideoViewItem.swift in Sources */,\n\t\t\t\t0321A53424D44E80004F1975 /* ActionCellView.swift in Sources */,\n\t\t\t\t0396D52124B8B7ED00CC021B /* Locations.swift in Sources */,\n\t\t\t\t0396D52224B8B7ED00CC021B /* VideoCache.swift in Sources */,\n\t\t\t\t0396D52324B8B7ED00CC021B /* BatteryIconLayer.swift in Sources */,\n\t\t\t\t030010AC24D71EB20092AE68 /* FiltersViewController.swift in Sources */,\n\t\t\t\t0396D52424B8B7ED00CC021B /* PrefsDisplays.swift in Sources */,\n\t\t\t\t0396D52624B8B7ED00CC021B /* Cache.swift in Sources */,\n\t\t\t\t0396D52824B8B7ED00CC021B /* AnimationTextLayer.swift in Sources */,\n\t\t\t\t0345D00F24C07CC70001045C /* VideoCellView.swift in Sources */,\n\t\t\t\t0345CFEE24BF43280001045C /* VideosViewController.swift in Sources */,\n\t\t\t\tF0058B8928ABF69B0053699B /* Sound.swift in Sources */,\n\t\t\t\t03EBF0C12746A53B00EC09D1 /* PlayingCollectionViewItem.swift in Sources */,\n\t\t\t\t0396D52924B8B7ED00CC021B /* InfoWeatherView.swift in Sources */,\n\t\t\t\t0396D52B24B8B7ED00CC021B /* SeededGenerator.swift in Sources */,\n\t\t\t\t0396D52C24B8B7ED00CC021B /* InfoDateView.swift in Sources */,\n\t\t\t\t0345EDE924C3239400C73038 /* DisplaysViewController.swift in Sources */,\n\t\t\t\t0396D52D24B8B7ED00CC021B /* ManifestLoader.swift in Sources */,\n\t\t\t\t03E168172673A23900D7442D /* InfoMusicView.swift in Sources */,\n\t\t\t\t037772E224E43AF300D81EEA /* TimeSetupViewController.swift in Sources */,\n\t\t\t\t0396D52E24B8B7ED00CC021B /* TimerLayer.swift in Sources */,\n\t\t\t\t0396D52F24B8B7ED00CC021B /* Source.swift in Sources */,\n\t\t\t\t0396D53024B8B7ED00CC021B /* PrefsInfo.swift in Sources */,\n\t\t\t\t0396D53124B8B7ED00CC021B /* ClockLayer.swift in Sources */,\n\t\t\t\t03298776274687340036D898 /* NowPlayingViewController.swift in Sources */,\n\t\t\t\t0396D53224B8B7ED00CC021B /* AerialVideo.swift in Sources */,\n\t\t\t\t0396D53324B8B7ED00CC021B /* ErrorLog.swift in Sources */,\n\t\t\t\t0396D53424B8B7ED00CC021B /* InfoSettingsView.swift in Sources */,\n\t\t\t\t03C605DD277B45CA005CA51F /* DispatchQueue+Extension.swift in Sources */,\n\t\t\t\t0396D53524B8B7ED00CC021B /* NSImage+trim.swift in Sources */,\n\t\t\t\t0396D53624B8B7ED00CC021B /* Battery.swift in Sources */,\n\t\t\t\t0396D53724B8B7ED00CC021B /* VideoList.swift in Sources */,\n\t\t\t\t0332076E26D7C355001F9837 /* AVAsset+VideoOrientation.swift in Sources */,\n\t\t\t\t0321A54524D5C863004F1975 /* NSButton+icons.swift in Sources */,\n\t\t\t\t0396D53824B8B7ED00CC021B /* InfoBatteryView.swift in Sources */,\n\t\t\t\t032E099F24C3897E00387230 /* AdvancedViewController.swift in Sources */,\n\t\t\t\t037772EE24E44CE100D81EEA /* RecapViewController.swift in Sources */,\n\t\t\t\t0396D53A24B8B7ED00CC021B /* DateLayer.swift in Sources */,\n\t\t\t\tF0058B8328ABF69B0053699B /* SoundOutputManager+Goodies.swift in Sources */,\n\t\t\t\t0396D53B24B8B7ED00CC021B /* AerialPlayerItem.swift in Sources */,\n\t\t\t\t0396D53C24B8B7ED00CC021B /* HardwareDetection.swift in Sources */,\n\t\t\t\t03EED2F124C44A7900F0C3D4 /* OverlaysViewController.swift in Sources */,\n\t\t\t\tF05E805528AE8A9C0088B9C5 /* NowPlayingCollectionView.swift in Sources */,\n\t\t\t\t0300B86A24D20B12006132E5 /* NextViewController.swift in Sources */,\n\t\t\t\t0396D53E24B8B7ED00CC021B /* YahooLogoLayer.swift in Sources */,\n\t\t\t\t0313329D24BF3FA700C84A05 /* SidebarViewController.swift in Sources */,\n\t\t\t\t0345D00B24BF4E8C0001045C /* Sidebar.swift in Sources */,\n\t\t\t\t0396D54024B8B7ED00CC021B /* InfoMessageView.swift in Sources */,\n\t\t\t\t03977F21250E7165008FBAFD /* TimeMachine.swift in Sources */,\n\t\t\t\t03BDBEA324C467EC00BBD5E9 /* BrightnessViewController.swift in Sources */,\n\t\t\t\t0396D54224B8B7ED00CC021B /* ConditionLayer.swift in Sources */,\n\t\t\t\t0396D54324B8B7ED00CC021B /* VideoManager.swift in Sources */,\n\t\t\t\t0378985F24C35F8A009B9418 /* CacheViewController.swift in Sources */,\n\t\t\t\t0396D54524B8B7ED00CC021B /* InfoContainerView.swift in Sources */,\n\t\t\t\t0396D54624B8B7ED00CC021B /* AerialView+Player.swift in Sources */,\n\t\t\t\t0396D54724B8B7ED00CC021B /* CustomVideoFolders+helpers.swift in Sources */,\n\t\t\t\t0396D54824B8B7ED00CC021B /* VideoLoader.swift in Sources */,\n\t\t\t\t03BDBEC124C4727C00BBD5E9 /* TimeViewController.swift in Sources */,\n\t\t\t\t0396D54924B8B7ED00CC021B /* TimeManagement.swift in Sources */,\n\t\t\t\t0396D54A24B8B7ED00CC021B /* DownloadIndicatorLayer.swift in Sources */,\n\t\t\t\t0396D54B24B8B7ED00CC021B /* CountdownLayer.swift in Sources */,\n\t\t\t\t031C5CB9268CA4E700CE35B4 /* ArtworkLayer.swift in Sources */,\n\t\t\t\t0396D54C24B8B7ED00CC021B /* SourceList.swift in Sources */,\n\t\t\t\t03B8742324E41CF8008E3D1B /* CacheSetupViewController.swift in Sources */,\n\t\t\t\t0396D54D24B8B7ED00CC021B /* DescriptionCellView.swift in Sources */,\n\t\t\t\t03FF1931269709AB00A0FA7F /* PlaybackSpeed.swift in Sources */,\n\t\t\t\t0396D54E24B8B7ED00CC021B /* DisplayView.swift in Sources */,\n\t\t\t\tF0A3E0A42884683D005E8D8D /* CompanionCacheViewController.swift in Sources */,\n\t\t\t\t0396D54F24B8B7ED00CC021B /* InfoLocationView.swift in Sources */,\n\t\t\t\t0396D55024B8B7ED00CC021B /* AssetLoaderDelegate.swift in Sources */,\n\t\t\t\t0396D55124B8B7ED00CC021B /* PrefsVideos.swift in Sources */,\n\t\t\t\t0396D55224B8B7ED00CC021B /* LocationLayer.swift in Sources */,\n\t\t\t\t0396D55424B8B7ED00CC021B /* InfoTableSource.swift in Sources */,\n\t\t\t\tF0058B8628ABF69B0053699B /* SoundOutputManager.swift in Sources */,\n\t\t\t\t0396D55524B8B7ED00CC021B /* Solar.swift in Sources */,\n\t\t\t\t03A6D15425F297CE00960135 /* WindDirectionLayer.swift in Sources */,\n\t\t\t\t03E1681B2673A63F00D7442D /* MusicLayer.swift in Sources */,\n\t\t\t\t0396D55624B8B7ED00CC021B /* Brightness.swift in Sources */,\n\t\t\t\t0300B84A24D1FD24006132E5 /* FirstSetupWindowController.swift in Sources */,\n\t\t\t\t0396D55724B8B7ED00CC021B /* SourceInfo.swift in Sources */,\n\t\t\t\t0338119624C1D15B002E23E0 /* Aerial.swift in Sources */,\n\t\t\t\t030010A324D706DB0092AE68 /* SidebarOutlineView.swift in Sources */,\n\t\t\t\t0396D55924B8B7ED00CC021B /* PrefsTime.swift in Sources */,\n\t\t\t\t0396D55A24B8B7ED00CC021B /* PoiStringProvider.swift in Sources */,\n\t\t\t\t0396D55B24B8B7ED00CC021B /* PrefsAdvanced.swift in Sources */,\n\t\t\t\t0396D55C24B8B7ED00CC021B /* WeatherLayer.swift in Sources */,\n\t\t\t\t0396D55D24B8B7ED00CC021B /* VideoDownload.swift in Sources */,\n\t\t\t\t0396D55E24B8B7ED00CC021B /* FileHelpers.swift in Sources */,\n\t\t\t\t0396D55F24B8B7ED00CC021B /* InfoSettingsTableSource.swift in Sources */,\n\t\t\t\t03F5551C24E9C091003AAD0B /* SourceOutlineView.swift in Sources */,\n\t\t\t\t0396D56024B8B7ED00CC021B /* DownloadManager.swift in Sources */,\n\t\t\t\t033811B124C1E243002E23E0 /* InfoViewController.swift in Sources */,\n\t\t\t\t03AA32632631A8F2002198C3 /* GeoCoding.swift in Sources */,\n\t\t\t\t031945F424CCC48C00F37B35 /* CreditsViewController.swift in Sources */,\n\t\t\t\t0396D56224B8B7ED00CC021B /* InfoCountdownView.swift in Sources */,\n\t\t\t\t0396D56324B8B7ED00CC021B /* ConditionSymbolLayer.swift in Sources */,\n\t\t\t\t03A6D14725F109B900960135 /* OpenWeather.swift in Sources */,\n\t\t\t\t0396D56424B8B7ED00CC021B /* CheckboxCellView.swift in Sources */,\n\t\t\t\t032851F8260A4C2C00684A81 /* OneCall.swift in Sources */,\n\t\t\t\t0317C19D268B65D10082A40C /* Music.swift in Sources */,\n\t\t\t\t03933B8C24C3986800A98D94 /* SourcesViewController.swift in Sources */,\n\t\t\t\t034DEE2F24BF1BC700A2D3CD /* PanelWindowController.swift in Sources */,\n\t\t\t\t0396D56524B8B7ED00CC021B /* AnimationLayer.swift in Sources */,\n\t\t\t\t0396D56624B8B7ED00CC021B /* AnimatableLayer.swift in Sources */,\n\t\t\t\t0396D56724B8B7ED00CC021B /* InfoClockView.swift in Sources */,\n\t\t\t\t0396D56824B8B7ED00CC021B /* CustomVideoController.swift in Sources */,\n\t\t\t\t03E2237224BE048900CD8ED4 /* VideoHeaderView.swift in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tFA143CD21BDA3E880041A82B /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t03B8742424E41CF8008E3D1B /* CacheSetupViewController.swift in Sources */,\n\t\t\t\tF07221892AD4354E001F5452 /* CompanionBridge.swift in Sources */,\n\t\t\t\t03D3A11524C5FC770091FE99 /* AspectFillNSImageView.swift in Sources */,\n\t\t\t\t031FB7A2248A873C0054BAFD /* PrefsCache.swift in Sources */,\n\t\t\t\tF00864B523AAE7F0003210EF /* DarkMode.swift in Sources */,\n\t\t\t\t031945FD24CCC52600F37B35 /* HelpViewController.swift in Sources */,\n\t\t\t\tF0058B8D28ABF69B0053699B /* SoundOutputManager+Properties.swift in Sources */,\n\t\t\t\t034A6DC624AF3EC600D62129 /* SourceList.swift in Sources */,\n\t\t\t\t03FA49B82428F84500863AF6 /* DateLayer.swift in Sources */,\n\t\t\t\t0361B9AC23D73D4500B6252D /* PrefsTime.swift in Sources */,\n\t\t\t\t037772EF24E44CE100D81EEA /* RecapViewController.swift in Sources */,\n\t\t\t\t0345D00C24BF4E8C0001045C /* Sidebar.swift in Sources */,\n\t\t\t\t030010A424D706DB0092AE68 /* SidebarOutlineView.swift in Sources */,\n\t\t\t\t032D1162239A7E03007E7756 /* Battery.swift in Sources */,\n\t\t\t\t03893CB4217753AC008E7125 /* ErrorLog.swift in Sources */,\n\t\t\t\t03C97BC124B60E2F00739CED /* FileHelpers.swift in Sources */,\n\t\t\t\t03233B692172762C0077D3F9 /* PoiStringProvider.swift in Sources */,\n\t\t\t\t03BF51C323A29E1D008AD373 /* ClockLayer.swift in Sources */,\n\t\t\t\t03EED2F224C44A7900F0C3D4 /* OverlaysViewController.swift in Sources */,\n\t\t\t\t0306336C23A143D900046A59 /* LayerOffsets.swift in Sources */,\n\t\t\t\t03A2CB9D216BB1490061E8E8 /* VideoManager.swift in Sources */,\n\t\t\t\t03BF17A124E2F29C0080EF34 /* VideoFormatViewController.swift in Sources */,\n\t\t\t\t033811B224C1E243002E23E0 /* InfoViewController.swift in Sources */,\n\t\t\t\t0354D0ED23F6CB7B00D86F9E /* InfoSettingsView.swift in Sources */,\n\t\t\t\t032851F9260A4C2C00684A81 /* OneCall.swift in Sources */,\n\t\t\t\tF0058B8728ABF69B0053699B /* SoundOutputManager.swift in Sources */,\n\t\t\t\t0321A53524D44E80004F1975 /* ActionCellView.swift in Sources */,\n\t\t\t\t0345D01024C07CC70001045C /* VideoCellView.swift in Sources */,\n\t\t\t\t03BDBEC224C4727C00BBD5E9 /* TimeViewController.swift in Sources */,\n\t\t\t\t03E87314216760B7002B469B /* TimeManagement.swift in Sources */,\n\t\t\t\t032851FD260A625100684A81 /* ForecastLayer.swift in Sources */,\n\t\t\t\t038C584B23A9394000224630 /* InfoCommonView.swift in Sources */,\n\t\t\t\t03A596D723AA75490097EA66 /* InfoMessageView.swift in Sources */,\n\t\t\t\t03F5551D24E9C091003AAD0B /* SourceOutlineView.swift in Sources */,\n\t\t\t\t03AA32642631A8F2002198C3 /* GeoCoding.swift in Sources */,\n\t\t\t\t03D1E78B22844AFD00D10CF7 /* DisplayDetection.swift in Sources */,\n\t\t\t\t03E8731021662AEB002B469B /* DownloadManager.swift in Sources */,\n\t\t\t\t03E8731121662AEB002B469B /* AsynchronousOperation.swift in Sources */,\n\t\t\t\t03E2237324BE048900CD8ED4 /* VideoHeaderView.swift in Sources */,\n\t\t\t\t0313329E24BF3FA700C84A05 /* SidebarViewController.swift in Sources */,\n\t\t\t\t03510C7121834FC7008F74F2 /* IOBridge.m in Sources */,\n\t\t\t\t03E1681C2673A63F00D7442D /* MusicLayer.swift in Sources */,\n\t\t\t\t032E09A024C3897E00387230 /* AdvancedViewController.swift in Sources */,\n\t\t\t\tF00864B823AAE8E9003210EF /* NightShift.swift in Sources */,\n\t\t\t\t03D1E7882284367200D10CF7 /* DisplayView.swift in Sources */,\n\t\t\t\t038D2EDF23B0FB0D00CD91F7 /* PrefsVideos.swift in Sources */,\n\t\t\t\t03DC0065248BC60D005DB0F4 /* Cache.swift in Sources */,\n\t\t\t\t038D2EE523B6565900CD91F7 /* InfoBatteryView.swift in Sources */,\n\t\t\t\t03A6D15525F297CE00960135 /* WindDirectionLayer.swift in Sources */,\n\t\t\t\t030D9B7C21551A8D00961E95 /* AerialPlayerItem.swift in Sources */,\n\t\t\t\t030A0F2A245C7C7D009E1D97 /* BatteryIconLayer.swift in Sources */,\n\t\t\t\t034587332449E22000C97D1B /* AnimationLayer.swift in Sources */,\n\t\t\t\t0300B86B24D20B12006132E5 /* NextViewController.swift in Sources */,\n\t\t\t\t03FA49A22423DA1F00863AF6 /* TimerLayer.swift in Sources */,\n\t\t\t\t03608A2D22A56465008F08A2 /* HardwareDetection.swift in Sources */,\n\t\t\t\t036A57D923F4747D0009DC02 /* InfoCountdownView.swift in Sources */,\n\t\t\t\tF0058B8A28ABF69B0053699B /* Sound.swift in Sources */,\n\t\t\t\t03C97BC424B6210500739CED /* SourceInfo.swift in Sources */,\n\t\t\t\t030473CD24BCA9A40094A1A6 /* VideoViewItem.swift in Sources */,\n\t\t\t\t0378986024C35F8A009B9418 /* CacheViewController.swift in Sources */,\n\t\t\t\t03C344FD24B778EE00906EA6 /* CheckboxCellView.swift in Sources */,\n\t\t\t\t03D3A10F24C5D7CC0091FE99 /* Thumbnails.swift in Sources */,\n\t\t\t\tFAC36F5E1BE1756D007F2A20 /* CheckCellView.swift in Sources */,\n\t\t\t\t034A6DC524ACC80B00D62129 /* Source.swift in Sources */,\n\t\t\t\t0338119724C1D15B002E23E0 /* Aerial.swift in Sources */,\n\t\t\t\tFAC36F5C1BE1756D007F2A20 /* AerialView.swift in Sources */,\n\t\t\t\t031C5CBA268CA4E700CE35B4 /* ArtworkLayer.swift in Sources */,\n\t\t\t\tFAC36F681BE1778C007F2A20 /* ManifestLoader.swift in Sources */,\n\t\t\t\t03FA49B52428EE3300863AF6 /* InfoDateView.swift in Sources */,\n\t\t\t\t0306336923A1026800046A59 /* LocationLayer.swift in Sources */,\n\t\t\t\t034F29C023A7E58C004B34D5 /* PrefsInfo.swift in Sources */,\n\t\t\t\t0385FC6D242BA097007E6513 /* InfoWeatherView.swift in Sources */,\n\t\t\t\t03C3450024B7A22300906EA6 /* DescriptionCellView.swift in Sources */,\n\t\t\t\t03BF51C023A275D9008AD373 /* MessageLayer.swift in Sources */,\n\t\t\t\t035D5250239AA31A00DC29DC /* AerialView+Player.swift in Sources */,\n\t\t\t\t0354D0EA23F6C3EE00D86F9E /* InfoSettingsTableSource.swift in Sources */,\n\t\t\t\t0385FC5A242B9AE1007E6513 /* APISecrets.swift in Sources */,\n\t\t\t\t0345872E2449C59900C97D1B /* AnimatableLayer.swift in Sources */,\n\t\t\t\t03C605DE277B45CA005CA51F /* DispatchQueue+Extension.swift in Sources */,\n\t\t\t\t0395834A217F442A008E8F9C /* Solar.swift in Sources */,\n\t\t\t\tFAB22A7F1BE17D7D0065C0F5 /* AssetLoaderDelegate.swift in Sources */,\n\t\t\t\t0332076F26D7C355001F9837 /* AVAsset+VideoOrientation.swift in Sources */,\n\t\t\t\t030010AD24D71EB20092AE68 /* FiltersViewController.swift in Sources */,\n\t\t\t\tFAC36F601BE175CF007F2A20 /* AppDelegate.swift in Sources */,\n\t\t\t\t03C97BA824B5F74900739CED /* VideoList.swift in Sources */,\n\t\t\t\t0345CFEF24BF43280001045C /* VideosViewController.swift in Sources */,\n\t\t\t\t03AD460022981B1C00261325 /* CustomVideoFolders+helpers.swift in Sources */,\n\t\t\t\t0361B9A923D732A300B6252D /* PrefsDisplays.swift in Sources */,\n\t\t\t\t032D1165239A7F17007E7756 /* AerialView+Brightness.swift in Sources */,\n\t\t\t\t031945F524CCC48C00F37B35 /* CreditsViewController.swift in Sources */,\n\t\t\t\tFA36BD401BE57F8E00D5E03B /* VideoDownload.swift in Sources */,\n\t\t\t\t0313F9F022955F3B00B074BB /* CustomVideoFolders.swift in Sources */,\n\t\t\t\t03BF51BD23A26522008AD373 /* LayerManager.swift in Sources */,\n\t\t\t\t03977F22250E7165008FBAFD /* TimeMachine.swift in Sources */,\n\t\t\t\t03933B8D24C3986800A98D94 /* SourcesViewController.swift in Sources */,\n\t\t\t\t0321A54624D5C863004F1975 /* NSButton+icons.swift in Sources */,\n\t\t\t\t0300B86324D2052B006132E5 /* WelcomeViewController.swift in Sources */,\n\t\t\t\t034116D423F9BD3100CD7674 /* PrefsUpdates.swift in Sources */,\n\t\t\t\t0345EDEA24C3239400C73038 /* DisplaysViewController.swift in Sources */,\n\t\t\t\tFAF450221BE2B45D00C1F98A /* VideoLoader.swift in Sources */,\n\t\t\t\t0317C19E268B65D10082A40C /* Music.swift in Sources */,\n\t\t\t\t03E168182673A23900D7442D /* InfoMusicView.swift in Sources */,\n\t\t\t\tF0058B8428ABF69B0053699B /* SoundOutputManager+Goodies.swift in Sources */,\n\t\t\t\t036A7E9D26370C260019186B /* Forecast.swift in Sources */,\n\t\t\t\t0374C9FF247AC5BC002F29D3 /* Locations.swift in Sources */,\n\t\t\t\t036A57DC23F5828E0009DC02 /* CountdownLayer.swift in Sources */,\n\t\t\t\t0313F9EA2294338300B074BB /* CustomVideoController.swift in Sources */,\n\t\t\t\t03A6D14825F109B900960135 /* OpenWeather.swift in Sources */,\n\t\t\t\tFAC36F5A1BE1756D007F2A20 /* AerialVideo.swift in Sources */,\n\t\t\t\t038D2EBD23AB91C300CD91F7 /* InfoLocationView.swift in Sources */,\n\t\t\t\t034F29B823A7A9B3004B34D5 /* InfoTableSource.swift in Sources */,\n\t\t\t\t03298777274687340036D898 /* NowPlayingViewController.swift in Sources */,\n\t\t\t\t0313F9ED2294468600B074BB /* SeededGenerator.swift in Sources */,\n\t\t\t\t034DEE3024BF1BC700A2D3CD /* PanelWindowController.swift in Sources */,\n\t\t\t\tF05E805628AE8A9C0088B9C5 /* NowPlayingCollectionView.swift in Sources */,\n\t\t\t\t03A4A80F2451D04C00A1F7A3 /* PrefsAdvanced.swift in Sources */,\n\t\t\t\t03FF1932269709AB00A0FA7F /* PlaybackSpeed.swift in Sources */,\n\t\t\t\t03A4A80C2451CE2C00A1F7A3 /* NSImage+trim.swift in Sources */,\n\t\t\t\t03FA49B22423DA7D00863AF6 /* InfoTimerView.swift in Sources */,\n\t\t\t\t0300B84B24D1FD24006132E5 /* FirstSetupWindowController.swift in Sources */,\n\t\t\t\t0393857B2175D4B80040B850 /* AVPlayerViewExtension.swift in Sources */,\n\t\t\t\t03A42AA12449F959003B3012 /* YahooLogoLayer.swift in Sources */,\n\t\t\t\t033842F824489EC600A2C523 /* WeatherLayer.swift in Sources */,\n\t\t\t\t038C584823A9308C00224630 /* InfoContainerView.swift in Sources */,\n\t\t\t\t03BF51BA23A24B40008AD373 /* AnimationTextLayer.swift in Sources */,\n\t\t\t\tF008DAFE23AADCFB00739DE1 /* Brightness.swift in Sources */,\n\t\t\t\tF0A3E0A52884683D005E8D8D /* CompanionCacheViewController.swift in Sources */,\n\t\t\t\t03A42AA4244A0E5F003B3012 /* ConditionLayer.swift in Sources */,\n\t\t\t\t03BDBEA424C467EC00BBD5E9 /* BrightnessViewController.swift in Sources */,\n\t\t\t\t036A57D623F30F490009DC02 /* DownloadIndicatorLayer.swift in Sources */,\n\t\t\t\t0300109924D6EF4C0092AE68 /* AVPlayerItem+vibrance.swift in Sources */,\n\t\t\t\t03A596D623AA752F0097EA66 /* InfoClockView.swift in Sources */,\n\t\t\t\t037772E324E43AF300D81EEA /* TimeSetupViewController.swift in Sources */,\n\t\t\t\t03047A5624D2DD8E000EFE62 /* NSMenuItem+icons.swift in Sources */,\n\t\t\t\t0345A24B24532E4600DD47CD /* ConditionSymbolLayer.swift in Sources */,\n\t\t\t\t03EBF0C22746A53B00EC09D1 /* PlayingCollectionViewItem.swift in Sources */,\n\t\t\t\tFAF450251BE2D2FD00C1F98A /* VideoCache.swift in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tFA71996A1D94EC5A00FBC99B /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tFA7199711D94EC5A00FBC99B /* PreferencesTests.swift in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tFACAF1A01BD9FC6000E539DC /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t03D1E78A2284471A00D10CF7 /* DisplayDetection.swift in Sources */,\n\t\t\t\tF07221872AD4354E001F5452 /* CompanionBridge.swift in Sources */,\n\t\t\t\t0306336B23A142FA00046A59 /* LayerOffsets.swift in Sources */,\n\t\t\t\t0385FC59242B9AE1007E6513 /* APISecrets.swift in Sources */,\n\t\t\t\tF00864B723AAE8E9003210EF /* NightShift.swift in Sources */,\n\t\t\t\tFAC36F5D1BE1756D007F2A20 /* CheckCellView.swift in Sources */,\n\t\t\t\t034116D323F9BD3100CD7674 /* PrefsUpdates.swift in Sources */,\n\t\t\t\t0300B86124D2052B006132E5 /* WelcomeViewController.swift in Sources */,\n\t\t\t\t03D3A10D24C5D7CC0091FE99 /* Thumbnails.swift in Sources */,\n\t\t\t\tFAC36F5B1BE1756D007F2A20 /* AerialView.swift in Sources */,\n\t\t\t\t03BF179F24E2F29C0080EF34 /* VideoFormatViewController.swift in Sources */,\n\t\t\t\t032851FB260A625100684A81 /* ForecastLayer.swift in Sources */,\n\t\t\t\t031FB78B248A87330054BAFD /* PrefsCache.swift in Sources */,\n\t\t\t\t0393857A2175D4B80040B850 /* AVPlayerViewExtension.swift in Sources */,\n\t\t\t\t03E8730F216501ED002B469B /* AsynchronousOperation.swift in Sources */,\n\t\t\t\t03BF51BC23A2643C008AD373 /* LayerManager.swift in Sources */,\n\t\t\t\t03510C6F21834F38008F74F2 /* IOBridge.m in Sources */,\n\t\t\t\tF00864B423AAE7F0003210EF /* DarkMode.swift in Sources */,\n\t\t\t\t03047A5424D2DD8E000EFE62 /* NSMenuItem+icons.swift in Sources */,\n\t\t\t\t0300109724D6EF4C0092AE68 /* AVPlayerItem+vibrance.swift in Sources */,\n\t\t\t\t0313F9EF22955F3B00B074BB /* CustomVideoFolders.swift in Sources */,\n\t\t\t\t036A7E9B26370C260019186B /* Forecast.swift in Sources */,\n\t\t\t\t030DDA902423C3BE0072D5C9 /* InfoTimerView.swift in Sources */,\n\t\t\t\t03BF51BF23A274CA008AD373 /* MessageLayer.swift in Sources */,\n\t\t\t\t038C584A23A9394000224630 /* InfoCommonView.swift in Sources */,\n\t\t\t\t031945FB24CCC52600F37B35 /* HelpViewController.swift in Sources */,\n\t\t\t\t032D1164239A7F0C007E7756 /* AerialView+Brightness.swift in Sources */,\n\t\t\t\t03D3A11324C5FC770091FE99 /* AspectFillNSImageView.swift in Sources */,\n\t\t\t\tF0058B8B28ABF69B0053699B /* SoundOutputManager+Properties.swift in Sources */,\n\t\t\t\t030473CB24BCA9A40094A1A6 /* VideoViewItem.swift in Sources */,\n\t\t\t\t0321A53324D44E80004F1975 /* ActionCellView.swift in Sources */,\n\t\t\t\t0374C9FE247AC5BC002F29D3 /* Locations.swift in Sources */,\n\t\t\t\tFAF450241BE2D2FD00C1F98A /* VideoCache.swift in Sources */,\n\t\t\t\t030A0F29245C7C7D009E1D97 /* BatteryIconLayer.swift in Sources */,\n\t\t\t\t030010AB24D71EB20092AE68 /* FiltersViewController.swift in Sources */,\n\t\t\t\t0361B9A823D732A300B6252D /* PrefsDisplays.swift in Sources */,\n\t\t\t\t03DC004E248BC5A4005DB0F4 /* Cache.swift in Sources */,\n\t\t\t\t0306336E23A15FA900046A59 /* AnimationTextLayer.swift in Sources */,\n\t\t\t\t0345D00E24C07CC70001045C /* VideoCellView.swift in Sources */,\n\t\t\t\t0345CFED24BF43280001045C /* VideosViewController.swift in Sources */,\n\t\t\t\tF0058B8828ABF69B0053699B /* Sound.swift in Sources */,\n\t\t\t\t03EBF0C02746A53B00EC09D1 /* PlayingCollectionViewItem.swift in Sources */,\n\t\t\t\t0385FC5D242B9F6E007E6513 /* InfoWeatherView.swift in Sources */,\n\t\t\t\t0313F9EC2294468600B074BB /* SeededGenerator.swift in Sources */,\n\t\t\t\t03FA49B42428EE3300863AF6 /* InfoDateView.swift in Sources */,\n\t\t\t\t0345EDE824C3239400C73038 /* DisplaysViewController.swift in Sources */,\n\t\t\t\tFAC36F671BE1778C007F2A20 /* ManifestLoader.swift in Sources */,\n\t\t\t\t03E168162673A23900D7442D /* InfoMusicView.swift in Sources */,\n\t\t\t\t037772E124E43AF300D81EEA /* TimeSetupViewController.swift in Sources */,\n\t\t\t\t03FA49A12423DA1F00863AF6 /* TimerLayer.swift in Sources */,\n\t\t\t\t034A6DC424ACC80200D62129 /* Source.swift in Sources */,\n\t\t\t\t034F29BF23A7E28E004B34D5 /* PrefsInfo.swift in Sources */,\n\t\t\t\t03BF51C223A2978B008AD373 /* ClockLayer.swift in Sources */,\n\t\t\t\t03298775274687340036D898 /* NowPlayingViewController.swift in Sources */,\n\t\t\t\tFAC36F591BE1756D007F2A20 /* AerialVideo.swift in Sources */,\n\t\t\t\t03893CB3217749F0008E7125 /* ErrorLog.swift in Sources */,\n\t\t\t\t0354D0EC23F6CB7B00D86F9E /* InfoSettingsView.swift in Sources */,\n\t\t\t\t03C605DC277B45CA005CA51F /* DispatchQueue+Extension.swift in Sources */,\n\t\t\t\t03A4A80B2451CE2C00A1F7A3 /* NSImage+trim.swift in Sources */,\n\t\t\t\t032D1161239A7D82007E7756 /* Battery.swift in Sources */,\n\t\t\t\t03C97BA724B5F74900739CED /* VideoList.swift in Sources */,\n\t\t\t\t0332076D26D7C355001F9837 /* AVAsset+VideoOrientation.swift in Sources */,\n\t\t\t\t0321A54424D5C863004F1975 /* NSButton+icons.swift in Sources */,\n\t\t\t\t038D2EE423B6565900CD91F7 /* InfoBatteryView.swift in Sources */,\n\t\t\t\t032E099E24C3897E00387230 /* AdvancedViewController.swift in Sources */,\n\t\t\t\t037772ED24E44CE100D81EEA /* RecapViewController.swift in Sources */,\n\t\t\t\t03FA49B72428F84500863AF6 /* DateLayer.swift in Sources */,\n\t\t\t\tF0058B8228ABF69B0053699B /* SoundOutputManager+Goodies.swift in Sources */,\n\t\t\t\tAA7E2E5E1FC62E8B00E5F320 /* AerialPlayerItem.swift in Sources */,\n\t\t\t\t03608A2C22A56465008F08A2 /* HardwareDetection.swift in Sources */,\n\t\t\t\t03EED2F024C44A7900F0C3D4 /* OverlaysViewController.swift in Sources */,\n\t\t\t\tF05E805428AE8A9C0088B9C5 /* NowPlayingCollectionView.swift in Sources */,\n\t\t\t\t0300B86924D20B12006132E5 /* NextViewController.swift in Sources */,\n\t\t\t\t03A42AA02449F959003B3012 /* YahooLogoLayer.swift in Sources */,\n\t\t\t\t0313329C24BF3FA700C84A05 /* SidebarViewController.swift in Sources */,\n\t\t\t\t0345D00A24BF4E8C0001045C /* Sidebar.swift in Sources */,\n\t\t\t\t03A596D323AA750F0097EA66 /* InfoMessageView.swift in Sources */,\n\t\t\t\t03977F20250E7165008FBAFD /* TimeMachine.swift in Sources */,\n\t\t\t\t03BDBEA224C467EC00BBD5E9 /* BrightnessViewController.swift in Sources */,\n\t\t\t\t03A42AA3244A0E5F003B3012 /* ConditionLayer.swift in Sources */,\n\t\t\t\t03A2CB9C216BA9AF0061E8E8 /* VideoManager.swift in Sources */,\n\t\t\t\t0378985E24C35F8A009B9418 /* CacheViewController.swift in Sources */,\n\t\t\t\t038C584723A9304800224630 /* InfoContainerView.swift in Sources */,\n\t\t\t\t035D524F239AA31A00DC29DC /* AerialView+Player.swift in Sources */,\n\t\t\t\t03AD45FF22981B0C00261325 /* CustomVideoFolders+helpers.swift in Sources */,\n\t\t\t\tFAF450211BE2B45D00C1F98A /* VideoLoader.swift in Sources */,\n\t\t\t\t03BDBEC024C4727C00BBD5E9 /* TimeViewController.swift in Sources */,\n\t\t\t\t03E8731321675FE0002B469B /* TimeManagement.swift in Sources */,\n\t\t\t\t036A57D523F30DD00009DC02 /* DownloadIndicatorLayer.swift in Sources */,\n\t\t\t\t036A57DB23F5820A0009DC02 /* CountdownLayer.swift in Sources */,\n\t\t\t\t031C5CB8268CA4E700CE35B4 /* ArtworkLayer.swift in Sources */,\n\t\t\t\t034A6DC224ACC7C800D62129 /* SourceList.swift in Sources */,\n\t\t\t\t03B8742224E41CF8008E3D1B /* CacheSetupViewController.swift in Sources */,\n\t\t\t\t03C344FF24B7A22300906EA6 /* DescriptionCellView.swift in Sources */,\n\t\t\t\t03FF1930269709AB00A0FA7F /* PlaybackSpeed.swift in Sources */,\n\t\t\t\t03D1E78722842FB300D10CF7 /* DisplayView.swift in Sources */,\n\t\t\t\tF0A3E0A32884683D005E8D8D /* CompanionCacheViewController.swift in Sources */,\n\t\t\t\t03A596D923AB8F000097EA66 /* InfoLocationView.swift in Sources */,\n\t\t\t\tFAB22A7E1BE17D7D0065C0F5 /* AssetLoaderDelegate.swift in Sources */,\n\t\t\t\t038D2EDE23B0FB0D00CD91F7 /* PrefsVideos.swift in Sources */,\n\t\t\t\t0306336823A1012200046A59 /* LocationLayer.swift in Sources */,\n\t\t\t\t034F29B723A7A93D004B34D5 /* InfoTableSource.swift in Sources */,\n\t\t\t\tF0058B8528ABF69B0053699B /* SoundOutputManager.swift in Sources */,\n\t\t\t\t03958349217F4416008E8F9C /* Solar.swift in Sources */,\n\t\t\t\t03A6D15325F297CE00960135 /* WindDirectionLayer.swift in Sources */,\n\t\t\t\t03E1681A2673A63F00D7442D /* MusicLayer.swift in Sources */,\n\t\t\t\tF008DAFD23AADCFB00739DE1 /* Brightness.swift in Sources */,\n\t\t\t\t0300B84924D1FD24006132E5 /* FirstSetupWindowController.swift in Sources */,\n\t\t\t\t03C97BC324B6210500739CED /* SourceInfo.swift in Sources */,\n\t\t\t\t0338119524C1D15B002E23E0 /* Aerial.swift in Sources */,\n\t\t\t\t030010A224D706DB0092AE68 /* SidebarOutlineView.swift in Sources */,\n\t\t\t\t0361B9AB23D73D4500B6252D /* PrefsTime.swift in Sources */,\n\t\t\t\t03233B68217272640077D3F9 /* PoiStringProvider.swift in Sources */,\n\t\t\t\t03A4A80E2451D04C00A1F7A3 /* PrefsAdvanced.swift in Sources */,\n\t\t\t\t033842E124489D7300A2C523 /* WeatherLayer.swift in Sources */,\n\t\t\t\tFA36BD3F1BE57F8E00D5E03B /* VideoDownload.swift in Sources */,\n\t\t\t\t03C97BC024B60E2F00739CED /* FileHelpers.swift in Sources */,\n\t\t\t\t0354D0E923F6C31800D86F9E /* InfoSettingsTableSource.swift in Sources */,\n\t\t\t\t03F5551B24E9C091003AAD0B /* SourceOutlineView.swift in Sources */,\n\t\t\t\t03E8730C2165013C002B469B /* DownloadManager.swift in Sources */,\n\t\t\t\t033811B024C1E243002E23E0 /* InfoViewController.swift in Sources */,\n\t\t\t\t03AA32622631A8F2002198C3 /* GeoCoding.swift in Sources */,\n\t\t\t\t031945F324CCC48C00F37B35 /* CreditsViewController.swift in Sources */,\n\t\t\t\t036A57D823F470940009DC02 /* InfoCountdownView.swift in Sources */,\n\t\t\t\t033D68812453080C0016F837 /* ConditionSymbolLayer.swift in Sources */,\n\t\t\t\t03A6D14625F109B900960135 /* OpenWeather.swift in Sources */,\n\t\t\t\t03C344FC24B778EE00906EA6 /* CheckboxCellView.swift in Sources */,\n\t\t\t\t032851F7260A4C2C00684A81 /* OneCall.swift in Sources */,\n\t\t\t\t0317C19C268B65D10082A40C /* Music.swift in Sources */,\n\t\t\t\t03933B8B24C3986800A98D94 /* SourcesViewController.swift in Sources */,\n\t\t\t\t034DEE2E24BF1BC700A2D3CD /* PanelWindowController.swift in Sources */,\n\t\t\t\t034587322449D8EB00C97D1B /* AnimationLayer.swift in Sources */,\n\t\t\t\t0345872D2449C52F00C97D1B /* AnimatableLayer.swift in Sources */,\n\t\t\t\t03A596D523AA752F0097EA66 /* InfoClockView.swift in Sources */,\n\t\t\t\t0313F9E822942B4500B074BB /* CustomVideoController.swift in Sources */,\n\t\t\t\t03E2237124BE048900CD8ED4 /* VideoHeaderView.swift in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXSourcesBuildPhase section */\n\n/* Begin PBXTargetDependency section */\n\t\tFA7199741D94EC5A00FBC99B /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = FA143CD51BDA3E880041A82B /* AerialApp */;\n\t\t\ttargetProxy = FA7199731D94EC5A00FBC99B /* PBXContainerItemProxy */;\n\t\t};\n/* End PBXTargetDependency section */\n\n/* Begin PBXVariantGroup section */\n\t\tFAC36F331BE1756D007F2A20 /* MainMenu.xib */ = {\n\t\t\tisa = PBXVariantGroup;\n\t\t\tchildren = (\n\t\t\t\tFAC36F341BE1756D007F2A20 /* Base */,\n\t\t\t);\n\t\t\tname = MainMenu.xib;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXVariantGroup section */\n\n/* Begin XCBuildConfiguration section */\n\t\t0396D5B324B8B7ED00CC021B /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tCLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = NO;\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCODE_SIGN_IDENTITY = \"Developer ID Application: Guillaume Louel (3L54M5L5KK)\";\n\t\t\t\tCODE_SIGN_STYLE = Manual;\n\t\t\t\tCOMBINE_HIDPI_IMAGES = YES;\n\t\t\t\tCURRENT_PROJECT_VERSION = 2.1.4beta1.appmode;\n\t\t\t\tDEFINES_MODULE = YES;\n\t\t\t\tDEVELOPMENT_TEAM = 3L54M5L5KK;\n\t\t\t\tENABLE_HARDENED_RUNTIME = YES;\n\t\t\t\tINFOPLIST_FILE = \"Aerial copy-Info.plist\";\n\t\t\t\tINSTALL_PATH = \"$(HOME)/Library/Screen Savers\";\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks\";\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.13;\n\t\t\t\tMARKETING_VERSION = 2.1.4beta1.appmode;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.johncoates.Aerial;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tPROVISIONING_PROFILE_SPECIFIER = \"\";\n\t\t\t\tSWIFT_OBJC_BRIDGING_HEADER = \"Aerial/Source/Models/Time/Aerial-Bridging-Header.h\";\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-Onone\";\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t\tWRAPPER_EXTENSION = saver;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t0396D5B424B8B7ED00CC021B /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tCLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = NO;\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCODE_SIGN_IDENTITY = \"Developer ID Application: Guillaume Louel (3L54M5L5KK)\";\n\t\t\t\tCODE_SIGN_STYLE = Manual;\n\t\t\t\tCOMBINE_HIDPI_IMAGES = YES;\n\t\t\t\tCURRENT_PROJECT_VERSION = 2.1.4beta1.appmode;\n\t\t\t\tDEFINES_MODULE = YES;\n\t\t\t\tDEVELOPMENT_TEAM = 3L54M5L5KK;\n\t\t\t\tENABLE_HARDENED_RUNTIME = YES;\n\t\t\t\tINFOPLIST_FILE = \"Aerial copy-Info.plist\";\n\t\t\t\tINSTALL_PATH = \"$(HOME)/Library/Screen Savers\";\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks\";\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.13;\n\t\t\t\tMARKETING_VERSION = 2.1.4beta1.appmode;\n\t\t\t\tOTHER_CODE_SIGN_FLAGS = \"--timestamp\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.johncoates.Aerial;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tPROVISIONING_PROFILE_SPECIFIER = \"\";\n\t\t\t\tSWIFT_OBJC_BRIDGING_HEADER = \"Aerial/Source/Models/Time/Aerial-Bridging-Header.h\";\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t\tWRAPPER_EXTENSION = saver;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\tFA143CE11BDA3E880041A82B /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tCODE_SIGN_IDENTITY = \"Mac Developer\";\n\t\t\t\tCODE_SIGN_STYLE = Automatic;\n\t\t\t\tCOMBINE_HIDPI_IMAGES = YES;\n\t\t\t\tCURRENT_PROJECT_VERSION = 2.1.4beta1.appmode;\n\t\t\t\tDEVELOPMENT_TEAM = 3L54M5L5KK;\n\t\t\t\tENABLE_TESTABILITY = YES;\n\t\t\t\tINFOPLIST_FILE = Aerial/App/Resources/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/../Frameworks\";\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.14;\n\t\t\t\tMARKETING_VERSION = 2.1.4beta1.appmode;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = \"com.johncoates.Aerial-Test\";\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tPROVISIONING_PROFILE_SPECIFIER = \"\";\n\t\t\t\tSWIFT_OBJC_BRIDGING_HEADER = \"Aerial/Source/Models/Time/Aerial-Bridging-Header.h\";\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-Onone\";\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tFA143CE21BDA3E880041A82B /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tCODE_SIGN_IDENTITY = \"Mac Developer\";\n\t\t\t\tCODE_SIGN_STYLE = Automatic;\n\t\t\t\tCOMBINE_HIDPI_IMAGES = YES;\n\t\t\t\tCURRENT_PROJECT_VERSION = 2.1.4beta1.appmode;\n\t\t\t\tDEVELOPMENT_TEAM = 3L54M5L5KK;\n\t\t\t\tENABLE_TESTABILITY = YES;\n\t\t\t\tINFOPLIST_FILE = Aerial/App/Resources/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/../Frameworks\";\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.14;\n\t\t\t\tMARKETING_VERSION = 2.1.4beta1.appmode;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = \"com.johncoates.Aerial-Test\";\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tPROVISIONING_PROFILE_SPECIFIER = \"\";\n\t\t\t\tSWIFT_COMPILATION_MODE = wholemodule;\n\t\t\t\tSWIFT_OBJC_BRIDGING_HEADER = \"Aerial/Source/Models/Time/Aerial-Bridging-Header.h\";\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\tFA7199761D94EC5A00FBC99B /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tBUNDLE_LOADER = \"$(TEST_HOST)\";\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_WARN_DOCUMENTATION_COMMENTS = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVES = YES;\n\t\t\t\tCODE_SIGN_IDENTITY = \"\";\n\t\t\t\tCOMBINE_HIDPI_IMAGES = YES;\n\t\t\t\tINFOPLIST_FILE = Tests/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks\";\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.12;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = \"com.johncoates.Aerial-Tests\";\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tSWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-Onone\";\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t\tTEST_HOST = \"$(BUILT_PRODUCTS_DIR)/AerialApp.app/Contents/MacOS/AerialApp\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tFA7199771D94EC5A00FBC99B /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tBUNDLE_LOADER = \"$(TEST_HOST)\";\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_WARN_DOCUMENTATION_COMMENTS = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVES = YES;\n\t\t\t\tCODE_SIGN_IDENTITY = \"\";\n\t\t\t\tCOMBINE_HIDPI_IMAGES = YES;\n\t\t\t\tINFOPLIST_FILE = Tests/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks\";\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.12;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = \"com.johncoates.Aerial-Tests\";\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t\tTEST_HOST = \"$(BUILT_PRODUCTS_DIR)/AerialApp.app/Contents/MacOS/AerialApp\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\tFACAF1AD1BD9FC6000E539DC /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = \"Accent Color\";\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_COMMA = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;\n\t\t\t\tCLANG_WARN_OBJC_LITERAL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_RANGE_LOOP_ANALYSIS = YES;\n\t\t\t\tCLANG_WARN_STRICT_PROTOTYPES = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = dwarf;\n\t\t\t\tENABLE_HARDENED_RUNTIME = YES;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tENABLE_TESTABILITY = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"DEBUG=1\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.12;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = YES;\n\t\t\t\tONLY_ACTIVE_ARCH = NO;\n\t\t\t\tOTHER_CODE_SIGN_FLAGS = \"--timestamp\";\n\t\t\t\tOTHER_SWIFT_FLAGS = \"-D DEBUG -DNOSPARKLE\";\n\t\t\t\tSDKROOT = macosx;\n\t\t\t\tSWIFT_VERSION = \"\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tFACAF1AE1BD9FC6000E539DC /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = \"Accent Color\";\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_COMMA = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;\n\t\t\t\tCLANG_WARN_OBJC_LITERAL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_RANGE_LOOP_ANALYSIS = YES;\n\t\t\t\tCLANG_WARN_STRICT_PROTOTYPES = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tENABLE_HARDENED_RUNTIME = YES;\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.12;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tOTHER_CODE_SIGN_FLAGS = \"--timestamp\";\n\t\t\t\tSDKROOT = macosx;\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-Owholemodule\";\n\t\t\t\tSWIFT_VERSION = \"\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\tFACAF1B01BD9FC6000E539DC /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tCLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = NO;\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCODE_SIGN_IDENTITY = \"Developer ID Application\";\n\t\t\t\tCODE_SIGN_STYLE = Manual;\n\t\t\t\tCOMBINE_HIDPI_IMAGES = YES;\n\t\t\t\tCURRENT_PROJECT_VERSION = 3.6.1;\n\t\t\t\tDEFINES_MODULE = YES;\n\t\t\t\tDEVELOPMENT_TEAM = 3L54M5L5KK;\n\t\t\t\tENABLE_HARDENED_RUNTIME = YES;\n\t\t\t\tINFOPLIST_FILE = \"$(SRCROOT)/Resources/Old stuff/Info.plist\";\n\t\t\t\tINSTALL_PATH = \"$(HOME)/Library/Screen Savers\";\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks\";\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.14;\n\t\t\t\tMARKETING_VERSION = 3.6.1;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.johncoates.Aerial;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tPROVISIONING_PROFILE_SPECIFIER = \"\";\n\t\t\t\tSWIFT_OBJC_BRIDGING_HEADER = \"Aerial/Source/Models/Time/Aerial-Bridging-Header.h\";\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-Onone\";\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t\tWRAPPER_EXTENSION = saver;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tFACAF1B11BD9FC6000E539DC /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tCLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = NO;\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCODE_SIGN_IDENTITY = \"Developer ID Application\";\n\t\t\t\tCODE_SIGN_STYLE = Manual;\n\t\t\t\tCOMBINE_HIDPI_IMAGES = YES;\n\t\t\t\tCURRENT_PROJECT_VERSION = 3.6.1;\n\t\t\t\tDEFINES_MODULE = YES;\n\t\t\t\tDEVELOPMENT_TEAM = 3L54M5L5KK;\n\t\t\t\tENABLE_HARDENED_RUNTIME = YES;\n\t\t\t\tINFOPLIST_FILE = \"$(SRCROOT)/Resources/Old stuff/Info.plist\";\n\t\t\t\tINSTALL_PATH = \"$(HOME)/Library/Screen Savers\";\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks\";\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.14;\n\t\t\t\tMARKETING_VERSION = 3.6.1;\n\t\t\t\tOTHER_CODE_SIGN_FLAGS = \"--timestamp\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.johncoates.Aerial;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tPROVISIONING_PROFILE_SPECIFIER = \"\";\n\t\t\t\tSWIFT_OBJC_BRIDGING_HEADER = \"Aerial/Source/Models/Time/Aerial-Bridging-Header.h\";\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t\tWRAPPER_EXTENSION = saver;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n/* End XCBuildConfiguration section */\n\n/* Begin XCConfigurationList section */\n\t\t0396D5B224B8B7ED00CC021B /* Build configuration list for PBXNativeTarget \"Aerial (low dependencies)\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t0396D5B324B8B7ED00CC021B /* Debug */,\n\t\t\t\t0396D5B424B8B7ED00CC021B /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\tFA143CE01BDA3E880041A82B /* Build configuration list for PBXNativeTarget \"AerialApp\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tFA143CE11BDA3E880041A82B /* Debug */,\n\t\t\t\tFA143CE21BDA3E880041A82B /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\tFA7199751D94EC5A00FBC99B /* Build configuration list for PBXNativeTarget \"Aerial Tests\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tFA7199761D94EC5A00FBC99B /* Debug */,\n\t\t\t\tFA7199771D94EC5A00FBC99B /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\tFACAF19F1BD9FC6000E539DC /* Build configuration list for PBXProject \"Aerial\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tFACAF1AD1BD9FC6000E539DC /* Debug */,\n\t\t\t\tFACAF1AE1BD9FC6000E539DC /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\tFACAF1AF1BD9FC6000E539DC /* Build configuration list for PBXNativeTarget \"Aerial\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tFACAF1B01BD9FC6000E539DC /* Debug */,\n\t\t\t\tFACAF1B11BD9FC6000E539DC /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n/* End XCConfigurationList section */\n\t};\n\trootObject = FACAF19C1BD9FC6000E539DC /* Project object */;\n}\n"
  },
  {
    "path": "Aerial.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:\">\n   </FileRef>\n</Workspace>\n"
  },
  {
    "path": "Aerial.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>IDEDidComputeMac32BitWarning</key>\n\t<true/>\n</dict>\n</plist>\n"
  },
  {
    "path": "Aerial.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict/>\n</plist>\n"
  },
  {
    "path": "Aerial.xcodeproj/xcshareddata/xcschemes/Aerial.xcscheme",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"1010\"\n   version = \"1.3\">\n   <BuildAction\n      parallelizeBuildables = \"YES\"\n      buildImplicitDependencies = \"YES\">\n      <BuildActionEntries>\n         <BuildActionEntry\n            buildForTesting = \"YES\"\n            buildForRunning = \"YES\"\n            buildForProfiling = \"YES\"\n            buildForArchiving = \"YES\"\n            buildForAnalyzing = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"FACAF1A41BD9FC6000E539DC\"\n               BuildableName = \"Aerial.saver\"\n               BlueprintName = \"Aerial\"\n               ReferencedContainer = \"container:Aerial.xcodeproj\">\n            </BuildableReference>\n         </BuildActionEntry>\n      </BuildActionEntries>\n   </BuildAction>\n   <TestAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\">\n      <Testables>\n      </Testables>\n   </TestAction>\n   <LaunchAction\n      buildConfiguration = \"Release\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      launchStyle = \"0\"\n      useCustomWorkingDirectory = \"NO\"\n      ignoresPersistentStateOnLaunch = \"YES\"\n      debugDocumentVersioning = \"NO\"\n      debugServiceExtension = \"internal\"\n      allowLocationSimulation = \"YES\">\n      <MacroExpansion>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"FACAF1A41BD9FC6000E539DC\"\n            BuildableName = \"Aerial.saver\"\n            BlueprintName = \"Aerial\"\n            ReferencedContainer = \"container:Aerial.xcodeproj\">\n         </BuildableReference>\n      </MacroExpansion>\n   </LaunchAction>\n   <ProfileAction\n      buildConfiguration = \"Release\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\"\n      savedToolIdentifier = \"\"\n      useCustomWorkingDirectory = \"NO\"\n      debugDocumentVersioning = \"YES\">\n      <MacroExpansion>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"FACAF1A41BD9FC6000E539DC\"\n            BuildableName = \"Aerial.saver\"\n            BlueprintName = \"Aerial\"\n            ReferencedContainer = \"container:Aerial.xcodeproj\">\n         </BuildableReference>\n      </MacroExpansion>\n   </ProfileAction>\n   <AnalyzeAction\n      buildConfiguration = \"Debug\">\n   </AnalyzeAction>\n   <ArchiveAction\n      buildConfiguration = \"Release\"\n      revealArchiveInOrganizer = \"YES\">\n      <PostActions>\n         <ExecutionAction\n            ActionType = \"Xcode.IDEStandardExecutionActionsCore.ExecutionActionType.ShellScriptAction\">\n            <ActionContent\n               title = \"Run Script\"\n               scriptText = \"# Type a script or drag a script file from your workspace to insert its path.&#10;\">\n            </ActionContent>\n         </ExecutionAction>\n      </PostActions>\n   </ArchiveAction>\n</Scheme>\n"
  },
  {
    "path": "AerialApp copy-Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIconFile</key>\n\t<string></string>\n\t<key>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>APPL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>$(MARKETING_VERSION)</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleVersion</key>\n\t<string>$(CURRENT_PROJECT_VERSION)</string>\n\t<key>LSApplicationCategoryType</key>\n\t<string>public.app-category.utilities</string>\n\t<key>LSMinimumSystemVersion</key>\n\t<string>$(MACOSX_DEPLOYMENT_TARGET)</string>\n\t<key>NSAppTransportSecurity</key>\n\t<dict>\n\t\t<key>NSAllowsArbitraryLoads</key>\n\t\t<true/>\n\t</dict>\n\t<key>NSHumanReadableCopyright</key>\n\t<string>Copyright © 2015 John Coates. All rights reserved.</string>\n\t<key>NSLocationAlwaysUsageDescription</key>\n\t<string>Aerial uses location services to calculate Sunset and Sunrise times from your position</string>\n\t<key>NSLocationWhenInUseUsageDescription</key>\n\t<string>Aerial uses location services to calculate Sunset and Sunrise times from your position</string>\n\t<key>NSMainNibFile</key>\n\t<string>MainMenu</string>\n\t<key>NSPrincipalClass</key>\n\t<string>NSApplication</string>\n\t<key>SUFeedURL</key>\n\t<string>https://raw.githubusercontent.com/JohnCoates/Aerial/master/appcast.xml</string>\n\t<key>SUPublicEDKey</key>\n\t<string>fbiQGEFq55xl4bjwj2/SpIO4JMsKmEyhHEWlMMueyDY=</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "Documentation/AutoUpdates.md",
    "content": "#  About auto-updates\n\nStarting with version 1.4.8, Aerial now includes the open source project [Sparkle](https://sparkle-project.org) to provide automatic updates. You can configure if and how you want this to work in the `Updates` tab:\n\n![Capture d’écran 2019-05-30 à 11 45 55](https://user-images.githubusercontent.com/37544189/58624482-a5eb9900-82d0-11e9-8a93-0aeb71988802.jpg)\n\nWhat you are seeing above are the out-of-the-box default. \n\n## Understanding the two settings\n\nBecause Aerial is \"just\" a screen saver (technically, a plugin to System Preferences), providing updates is slightly more involved and because of this, we have two, separate, automatic update mechanisms with two separate settings to control them:\n\n- The first setting controls whether you want automatic updates or not. This check is done periodically (if 24 hours elapsed since last check), but *only* when the screen saver panel (the one you see in the screenshot) is open. When an update is available, you will see this window pop:\n\n![Capture d’écran 2019-05-30 à 11 58 34](https://user-images.githubusercontent.com/37544189/58625280-6a51ce80-82d2-11e9-8dd0-a5ed92fa74f4.jpg)\n\nYou can then decide if you want to install or not, the checkbox controls whether you want this to be done automatically for you *for this specific mechanism*. \n\n- The second setting controls whether you want Aerial to update itself while the screen saver is running. Because most people don't fiddle everyday with their screen saver settings, we've added this secondary mechanism to Aerial so everyone can stay up to date. Unlike the first mechanism above, this one is silent, and having this option enabled will automatically install the latest update without prompting you. The check is periodic (if 24 hours elapsed since last check), and done when the screen saver starts. If an update is available, the screen saver will exit, install the update, and open system preferences with the new version of Aerial. Your system will go back to sleep eventually.  \n\nWhile we recognize that the second mechanism is highly perfectible, this is the only workaround we've found with Sparkle to provide automatic updates while Aerial runs, or without having some sort of \"helper\" app always running on your system to check for updates. Unless you want to manualy manage your updates, we highly recommend you keep this checked!\n\n## Beta updates\n\nThe third checkbox lets you opt-in to the beta updates. Beta releases are used to test fixes to reported issues, latest videos and new features. They are usually pretty stable. If you want those beta versions, you can enable this checkbox. Note that when a new non-beta release is available after the beta process, it will also be available in the beta track, so you are always up to date!\n\n## What kind of network traffic does that entail? \n\nWhen a check happens, the auto update loads a [XML file from the GitHub repository](https://github.com/JohnCoates/Aerial/blob/master/appcast.xml) for the new updates. The updates are then downloaded from the GitHub repository's \"Releases\" section, the download link is included in the XML, they are always in the form of `https://github.com/JohnCoates/Aerial/releases/download/v1.5.0/Aerial.saver.zip` . \n\nWhile Sparkle optionally allows to [collect anonymous user data](https://sparkle-project.org/documentation/system-profiling/), we **do not** use this feature and **do not** collect any form of data whatshowever.\n\n## Security?\n\nEach update is signed with a private EdDSA key when a release is built by the maintainer ([glouel](https://github.com/glouel). The [appcast.xml](https://github.com/JohnCoates/Aerial/blob/master/appcast.xml) provides that signature (and file size, for example for 1.4.9 :  `sparkle:edSignature=\"5QFV0eqGRqCoZ8/TYbLXWOiVSifwNRUk4wuNFdjXJXpk/cRrceaTcs7SG168dawfOTpy9TOu283mb6WJGRQuDw==\" length=\"5674805\"` ) which will be checked against the public key bundled with Aerial. If the signature doesn't match, the update won't be installed. Each `Aerial.saver` is also signed with my ([glouel](https://github.com/glouel)) Apple ID certificate, which is also [checked by Sparkle](https://github.com/sparkle-project/Sparkle/issues/1283). Starting with 1.5.1 all Aerial builds are also notarized by Apple.\n\n## Installed for all users and password prompt\n\nIf you installed the screen saver for all users the first time (instead of for your individual user), macOS prompted you at install for your administrator password. The same thing will happen for automatic updates with the two mechanisms. Because of this, with the \"Auto update when screen saver runs\" checked, you will get a password prompt from Aerial/Sparkle when waking up your system.\n\nThis is working as intended for macOS, if you are bothered by those prompt, consider reinstalling Aerial for your user account only. If you have multiple accounts, you can still install Aerial for each account, by default each will use the same shared cache for videos (in `/Library/Caches/Aerial/`).\n\n## Homebrew and auto-updates\n\nIf you installed Aerial through Homebrew, you will get updates automatically from that channel. Note that because of the way brew cask works, it may take a few hours for the update to show, compared to the Sparkle auto-update. We recommend that you disable the built in auto-updates if you use Homebrew. \n"
  },
  {
    "path": "Documentation/ChangeLog.md",
    "content": "#  Aerial change log\n\n## [1.8.0](https://github.com/JohnCoates/Aerial/releases/tag/v1.8.0) - February 18, 2020\n\n- New update system for macOS Catalina. Starting with version 1.8.0, Aerial will now by default notify you with a message while the screen saver runs, when a new version of Aerial is available :\n\n![Capture d’écran 2020-02-18 à 17 57 39](https://user-images.githubusercontent.com/37544189/74758954-5858f700-5278-11ea-8e17-d034fdf57f33.jpg)\n\nYou will also be notified when a new version is available in Aerial's settings, with that new mechanism that will redirect you to the new release page where you can download the new version :\n![Capture d’écran 2020-02-18 à 17 59 28](https://user-images.githubusercontent.com/37544189/74759068-7f172d80-5278-11ea-99bf-08621550087b.jpg)\n\nThe update check process still uses Sparkle, but Aerial is not able to auto update in macOS Catalina due to the new sandboxing restrictions. I apologize for the inconvenience.\n\n- Add new shadow controls :\n\n![Capture d’écran 2020-02-18 à 18 06 26](https://user-images.githubusercontent.com/37544189/74759836-b3d7b480-5279-11ea-84cf-3ddbc810cbce.jpg)\n\n- Add a new Countdown information option, to either countdown to a given date, or a given time of day :\n\n![Capture d’écran 2020-02-18 à 18 07 49](https://user-images.githubusercontent.com/37544189/74759838-b4704b00-5279-11ea-8446-9cad67da60ea.jpg)\n\nThis version also fixes many issues with macOS Catalina, namely localization that always defaulted to English, due to the restrictions applied by `legacyScreenSaver.appex`'s sandboxing. Starting with 1.8.0, Aerial requires at least macOS 10.12.\n## [1.7.1](https://github.com/JohnCoates/Aerial/releases/tag/v1.7.1) - February 11, 2020\n\n- Brings back \"Allow right arrow to skip\" for macOS versions prior to Catalina. That feature still won't work on Catalina.\n- Add seamless looping if you only have one video in your playlist.\n- Fix \"new style\" settings that weren't saved immediately, causing a discrepancy if you didn't close the preferences panel before launching the screen saver (with a hot corner).\n\n## [1.7.0](https://github.com/JohnCoates/Aerial/releases/tag/v1.7.0) - January 29, 2020\n\n- Add support for the 11 new sea videos that were just released, including dolphins, sharks and Tahiti waves.\n\n![Capture d’écran 2020-01-29 à 20 52 20](https://user-images.githubusercontent.com/37544189/73392796-ca25cc80-42da-11ea-913a-c4dc1f310710.jpg)\n\n- Complete rewrite of the text/animation system, you can now select which information appears on which display, and configure more precisely the position of items on screen, or the font used. \n\n![Capture d’écran 2020-01-29 à 21 00 08](https://user-images.githubusercontent.com/37544189/73392613-731ff780-42da-11ea-8421-8149f24be6e1.jpg)\n\nThis version also fixes many issues with macOS Catalina.\n\n## [1.6.0](https://github.com/JohnCoates/Aerial/releases/tag/v1.6.0) - September 26, 2019\n\n- Support for the 15 new videos included in tvOS 13, including the ten new underwater seascape videos and five new ISS space videos. \n\n![Capture d’écran 2019-09-26 à 15 29 20](https://user-images.githubusercontent.com/37544189/65692345-a9224600-e072-11e9-8c60-b0e0e546ad31.jpg)\n\n- The HDR versions of videos can now be played by Aerial. This requires macOS 10.15 Catalina, please note that you will need to redownload the HDR versions of those videos. \n\n![Capture d’écran 2019-09-26 à 15 26 34](https://user-images.githubusercontent.com/37544189/65692344-a889af80-e072-11e9-8eac-361ba1f5d980.jpg)\n\n- Improved advanced multi monitor support. Advanced users can now finely specify the distance between each of their screens in the new \"Spanned\" mode included in Aerial 1.5.0, in order to accomodate more complex configurations.\n\n![Capture d’écran 2019-09-26 à 15 24 08](https://user-images.githubusercontent.com/37544189/65692342-a889af80-e072-11e9-81ad-de70c7b2f0a1.jpg)\n\n- Support for macOS 10.15 Catalina. macOS Catalina includes new restrictions on third party screen savers, which impact some of the functionnalities. We highly suggest that current and would be Catalina users check this issue for more information on those restrictions : https://github.com/JohnCoates/Aerial/issues/801\n\n![Capture d’écran 2019-09-26 à 15 23 45](https://user-images.githubusercontent.com/37544189/65692340-a889af80-e072-11e9-8109-cdcd8f55fe86.jpg)\n\nAerial is also now properly signed and notarized to comply with new restrictions introduced in macOS 10.15 Catalina. \n\nThis version also includes many bugfixes, including bugs regarding multi monitor setups and previous versions of macOS.\n\n## [1.5.0](https://github.com/JohnCoates/Aerial/releases/tag/v1.5.0) - May 31, 2019\n\n- Completely rewritten multi monitor support. You can now enable and disable individual displays in the new Display tab:\n\n![Capture d’écran 2019-05-29 à 14 44 01](https://user-images.githubusercontent.com/37544189/58558340-d116af80-8220-11e9-9081-696d805c1e29.jpg)\n\n- New \"Spanned\" viewing mode. Selecting this mode will span an Aerial video on all your (selected) screens. You can even adjust margins:\n\n![Capture d’écran 2019-05-29 à 14 43 52](https://user-images.githubusercontent.com/37544189/58558342-d116af80-8220-11e9-8bb0-8d26f1e1b6ed.jpg)\n\n- Add your own videos to Aerial using the new Custom Videos features. You can add your own videos in the new video manager (found in the menu below the video list):\n\n![Capture d’écran 2019-05-30 à 18 01 36](https://user-images.githubusercontent.com/37544189/58646171-24fac480-8305-11e9-98fd-c9ec7ef3a64c.jpg)\n\nYou can find more [information here](CustomVideos.md).\n\n- You can now remove a single video from cache by right clicking it.\n- Sparkle updated to 1.21.3.\n- And many bug fixes!\n\n## [1.4.9](https://github.com/JohnCoates/Aerial/releases/tag/v1.4.9) - May 1, 2019\n\n- Fix a crashing bug in 1.4.8 for homebrew users. \n\n## [1.4.8](https://github.com/JohnCoates/Aerial/releases/tag/v1.4.8) - April 30, 2019\n\n- Add support for the 5 new 4K videos (January 25th update).\n- Automatic updates through Sparkle.\n\n![Capture d’écran 2019-04-30 à 18 31 20](https://user-images.githubusercontent.com/37544189/56977789-4afe3f00-6b76-11e9-9985-1ca1a1866d6b.jpg)\n\n- Localization for community support in Arabic, Chinese Simplified, English, French, German, Hebrew, Polish and Spanish! Thanks to all the contributors. If you want to help, check here, we very much welcome new contributions !\n- You can now skip an Aerial with the right arrow key.\n- You can now save your favorite videos sets to enable them quickly (look for the bookmark icon below the video list).\n- And many bug fixes!\n\n## [1.4.6](https://github.com/JohnCoates/Aerial/releases/tag/v1.4.6) - December 28, 2018\n\n- **25 extra videos now available in 4K:** Following the content updates from October 30th and December 5th, Aerial now includes 70 videos, 60 of which are also available in 4K. Aerial will periodically check for new videos, you can disable this feature in the `Cache` tab.\n\n![screen shot 2018-10-29 at 13 21 05](https://user-images.githubusercontent.com/37544189/47649972-1f76a980-db7f-11e8-910b-1d5d50931ae2.png)\n\n- **Show videos in Quicktime:** You can now right click a video to open it in Quicktime.\n- **Remove video duplicates:** Aerial can now cleanup your old videos (They are periodically updated to fix colors, provide longer versions of previously existing videos, or upgraded to 4K). Go to the `Advanced` Tab and either move the files away or send them to the trash to reclaim free space. The `Move old videos` button will move the video files to a directory created within the Aerial cache called `oldvideos`, which will contain a dated directory within it. You can find them at `/Users/YOURUSERNAME/Library/Caches/Aerial/oldvideos/YYYY-MM-DD`\n\n![capture d ecran 2018-12-13 a 15 06 49](https://user-images.githubusercontent.com/37544189/49943901-60394080-fee9-11e8-93b0-3cc68087b70e.png)\n\n\n## [1.4.5](https://github.com/JohnCoates/Aerial/releases/tag/v1.4.5) - November 3, 2018\n\n- **More battery controls:** Using Aerial on a Macbook ? You can now specify a different video format on battery mode if you wish, or simply video playback using the Power Saving mode (Aerial will show a blank screen and reduce screen brightness instead of showing videos).\n- You can now show day/night videos based on Dark Mode.\n- And many bug fixes!\n\n## [1.4.4](https://github.com/JohnCoates/Aerial/releases/tag/v1.4.4) - October 29, 2018\n\n- New sunset/sunrise dusk/dawn calculation modes from coordinates, Aerial can gather your location using your Mac's location service (you'll be asked for permission). Includes multiple calculations modes for dusk to better suite everyone's needs\n\n![screen shot 2018-10-29 at 13 24 46](https://user-images.githubusercontent.com/37544189/47649974-1f76a980-db7f-11e8-8339-3f0424652b8c.png)\n\n- Control brightness, Aerial can progressively dim the brightness of your screen when it plays. Includes extra options to only enable at night or on battery\n\n![screen shot 2018-10-29 at 13 25 10](https://user-images.githubusercontent.com/37544189/47649975-200f4000-db7f-11e8-9e8b-f75c4a5ebde4.png)\n\n- Add an option to define the margins from the border where descriptions should appear, changed the default for something more sensible\n- And many bug fixes/ui tweaks!\n\n## [1.4.3](https://github.com/JohnCoates/Aerial/releases/tag/v1.4.3) - October 23, 2018\n\n- Fix a memory retain cycle while downloading or playing cached videos\n\n## [1.4.2](https://github.com/JohnCoates/Aerial/releases/tag/v1.4.2) - October 23, 2018\n\n- Community location description, with better descriptions on many of the older videos (english only for this version)\n- Updated video names\n- Added logging options in Advanced panel, with better error messages when something goes wrong\n- You can now stop video downloads\n- You can now disable seconds on clock\n- We now have a retina(ish) thumbnail in System Preferences\n\n## [1.4.1](https://github.com/JohnCoates/Aerial/releases/tag/v1.4.1) - October 16, 2018\n\n- Better names for the videos\n- New location information for \"old\" videos (London, SF, etc)\n- You can now change the font/size of the location information displayed during videos\n- New options for text display (custom message, same styled clock, etc)\n- Add a \"Main display only\" option for multiple monitor setups\n\n## [1.4.0](https://github.com/JohnCoates/Aerial/releases/tag/v1.4) - October 11, 2018\n\n- Every Aerial video: From the very first Aerials in San Francisco to the new space videos shot from the ISS!\n- 4K HEVC: With the launch of Apple TV 4K, many videos are now available in this format. Aerial will show you the best format available based on your preferences.\n- Different videos based on time: Want to see night videos at night? You can either specify your sunset or sunrise time manually, or, if your Mac is compatible with Night Shift (see here for a list of compatible Mac), get those automatically (you do not need to enable Night Shift).\n- Feeling Dark?: Aerial is now compatible with Dark Mode in macOS 10.14 Mojave, and can play night videos when Dark Mode is enabled.\n- Descriptions: Wondering where an Aerial view was shot? Aerial can now tell you as they play.\n- Full offline mode:: Behind a firewall? Just copy the cache folder from another Mac and you are all set. You can also disable all streaming.\nBetter cache management: You can now cache your favorite videos individually, no need to grab them all. Or just stream them as you go, they'll get cached automatically too.\n\n\n## [1.2beta5](https://github.com/JohnCoates/Aerial/releases/tag/v1.2beta5) - December 28, 2016\n\n- Latest beta from @JohnCoates\n\nYou can find more information about older versions and betas in the project [Release history](https://github.com/JohnCoates/Aerial/releases).\n"
  },
  {
    "path": "Documentation/Contribute.md",
    "content": "# Contributing to Aerial\n\n(If you want to help with translations, please check [this page here](https://github.com/JohnCoates/Aerial/blob/master/Resources/Community/Readme.md).)\n\nIf you want to contribute code to Aerial, you are more than welcome!\n\nFeel free to directly submit a PR for small changes or quick bug fixes, so we can have a look. \n\nIf you want to implement something more substantial, it might be a good idea to open an issue first to discuss what you want to do, so we can coordinate efforts and help you get around the existing codebase and it's various pitfalls. \n\n# Warning if you setup your repo prior to 1.7.2\n\nStarting with version 1.7.2, we've removed the cocoapods dependency to Sparkle, and replaced it with a git submodule reference in /Extern). I strongly recomend you pull anew. If you still want to fix your existing repo I would suggest :\n\n```\npod deintegrate\ngit pull\ngit submodule update --init --recursive\n```\n\nFrom your main repo folder. \n\n\n# How to compile Aerial\n\nThis is the easiest way to pull Aerial. \n\n- From terminal in a suitable location, run `git clone --recurse-submodules https://github.com/JohnCoates/Aerial.git`. This will bring Aerial and it's dependencies (Sparkle).  \n- In the future, if you wish to update Sparkle, you can run `git submodule update --init --recursive` \n- Open the `Aerial.xcodeproj` in Xcode\n- Top left of the screen, pick the \"AerialApp\" scheme :\n![Capture d’écran 2019-06-27 à 12 56 42](https://user-images.githubusercontent.com/37544189/60261086-569e8580-98db-11e9-8fd2-e579786f628d.jpg)\n- Build and run. \n\nThe AerialApp scheme compiles Aerial as an App, instead of a screensaver, so you can more easily test and debug your code in Xcode. Use the Aerial scheme to compile as a screensaver. \n\nIf you are running into an issue, feel free to open an issue so we can assist you.\n"
  },
  {
    "path": "Documentation/CustomVideos.md",
    "content": "#  Add your own videos to Aerial\n\nStarting with version 1.5.0 of Aerial, you can now add your own videos to the playlist. In order to do this, click \"Custom Videos...\" at the bottom of the menu:\n\n![Capture d’écran 2019-05-24 à 17 13 22](https://user-images.githubusercontent.com/37544189/58338271-c090be80-7e47-11e9-833a-d70ada56232b.jpg)\n\nThis will open the \"Manage Custom Videos\" window. \n\n![Capture d’écran 2019-05-30 à 17 45 15](https://user-images.githubusercontent.com/37544189/58646170-24622e00-8305-11e9-9235-9e7960bdf95e.jpg)\n\nClick the \"Add folder\" at the top of the window, and point it to a folder that contains videos. Aerial will scan that folder and show you the videos it found in the left panel. For long time users, a good way to try this is your `oldvideos` folder in your Aerial cache folder. \n\n**WARNING !!!!** If you are using Catalina, because of sandboxing restrictions, Aerial will not be able to load videos from your `Documents` folder, or the `Desktop` (precisely, you will be able to add them, but as soon as you close System Preferences or launch the full screen screensaver, Aerial will not be able to open them again and you'll get an error with a Play button in the preview, and a black screen in fullscreen mode). To get it to work in Catalina, please create a folder in `/Users/Shared/`, put your videos there and add them to Aerial from there.    \n\n## Folders and files\n\nAerial will scan your folder for video files, including subfolders. After scanning, all these video files will show up in the left column, grouped under the name of the folder you picked. \n\n![Capture d’écran 2019-05-24 à 17 13 44](https://user-images.githubusercontent.com/37544189/58338555-36952580-7e48-11e9-8f9b-4e69a48dc11b.jpg)\n\nYou can override that name here. This folder name will be used to categorize those videos in the playlist, akin to the classical \"city/country\" category you see for Aerial videos. If you use an existing name (for example \"Los Angeles\"), videos will be merged in the playlist. \n\nIf you click a file, you'll get the asset editor: \n\n![Capture d’écran 2019-05-30 à 18 01 36](https://user-images.githubusercontent.com/37544189/58646171-24fac480-8305-11e9-98fd-c9ec7ef3a64c.jpg)\n\n\nYou can change the name of the video, whether it's a day or night video (by default every file is imported as day) and let's you add points of interests. Points of interests are the descriptions that are shown periodically on screens when videos play. The format is simple, a time in seconds, and the description you would like to appear. We highly recommend you leave at least 10 to 15 seconds between two points of interests. \n\n![Capture d’écran 2019-05-29 à 12 52 29](https://user-images.githubusercontent.com/37544189/58552781-8478a780-8213-11e9-99bc-2b55c75b6bd3.jpg)\n\n## How is this stored ?\n\nWhen you close the window, all the information will be saved in a `customvideos.json` file in your Aerial cache folder. The format is close to the tvOS12 format, and can be edited manually. \n\n## Video formats/containers supported\n\nAs of version 1.5.0, Aerial will only look for .mov or .mp4 files (if you would like to see another extension added, please let us know but keep reading first). Aerial uses Apple's AVFoundation framework to play videos. Long story short, in theory anything that QuickTime Player X can play, will work with Aerial. As of macOS Mojave, this means that some container formats such as mkv won't be supported.  \n"
  },
  {
    "path": "Documentation/FAQs.md",
    "content": "# Frequently Asked Questions\n\nThis guide is meant to help you get started and answer some of the most common questions. If you wish to search for a specific term, please type `Command` + `F` and search for a single word such as \"favorites\".\n\n<hr> \n\n## How do I install Aerial?\n\nIf this is your first time on GitHub or you are not a \"power user\" we reccomend the following setup:\n\n1. Navigate to the [latest releases](https://github.com/glouel/AerialCompanion/releases)\n2. Select `AerialInstaller.dmg` on the most recent release (which is on the top). Disregard the remaining files/assets.\n3. Navigate to your Downloads folder (or wherever you chose to save `AerialInstaller.dmg`)\n4. Double click on `AerialInstaller.dmg` \n5. It will momentarily pause to open the DMG file.\n6. You will then see a window that prompts you to drag `Aerial.app` to the `Applications` folder. Please do so. \n\n![Drag and Drop](https://user-images.githubusercontent.com/18543749/90923714-24dc5e00-e3bc-11ea-9a24-a650f42ea734.gif)\n\n7. Now double click on the `Applications` folder that you just dragged the icon to. \n8. Find and double click on `Aerial.app` \n9. This will launch and install Aerial. You will notice a small circle in your menubar (at the top of your screen)\n10. Lastly, go to the menubar, click on the icon and select `Open screen saver settings...`\n\n<img width=\"150\" alt=\"Screen Saver Settings\" src=\"https://user-images.githubusercontent.com/18543749/90923886-77b61580-e3bc-11ea-97c6-ac90647f2e71.png\">\n\n11. Click on the \"Screen Saver\" tab at the top of System Preferences\n12. And select Aerial on the left hand side. \n13. You're all set! If you want to change your settings, simply click on `Screen Saver Options...` on the right hand side. \n14. You can now eject (delete) `AerialInstaller.dmg`\n\n<hr>\n\n## How do I change my settings?\n\n1. Open System Preferences \n2. Click on Desktop & Screen Saver in System Preferences \n\n<img width=\"128\" alt=\"Desktop and Screen Saver Prefs\" src=\"https://user-images.githubusercontent.com/18543749/90852443-831a2a00-e345-11ea-81ce-48b7632cd537.png\">\n\n3. Scroll down until you see \"Aerial\" in the left hand panel\n4. Click on `Screen Saver Options` \n\n<img width=\"200\" alt=\"Screen Saver Options\" src=\"https://user-images.githubusercontent.com/18543749/90852516-aa70f700-e345-11ea-89f3-0323eb24ebd1.png\">\n\n5. Now you are ready to manage your Aerial settings! \n\n<hr> \n\n## Videos not playing\n\nIf you have a selection of videos you want to play, but they aren't playing check the following: \n\n- *Have you selected the videos you want to play?*\n- *Have you cached the videos you want to play?* \n\n#### Have you selected the videos you want to play?\n\nYou can do this in two different ways. Either *favorite* the videos and then choose to play only your favorites, or *limit the selection* of videos that you play. \n\n#### To play only favorites:\n1. Open Aerial in System Preferences \n2. Favorite (by starring) the videos you want to play. You can favorite an entire selection by right clicking on the left hand panel)\n\n<img width=\"254\" alt=“Favorite from Panel src=\"https://user-images.githubusercontent.com/18543749/90850889-0422f280-e341-11ea-945a-4b86255a9e4c.png\">\n\n3. Click on the `On Rotation` tab in the sidebar (at the top)\n4. At the top of System Preferences, click on the dropdown next the `Aerial current plays:` and select `Only Favorites`.\n\n<img width=\"345\" alt=\"Play Only Favorites\" src=\"https://user-images.githubusercontent.com/18543749/90850948-33d1fa80-e341-11ea-8132-78f08a7ae9cc.png\">\n\n### To play a single category of videos:\n\n1. Open Aerial in System Preferences \n2. Click on the `On Rotation` tab in the sidebar (at the top)\n3. At the top of System Preferences, click on the dropdown next to `Aerial current plays:` and select `Location`, `Time`, `Scene`, or `Source` then select the proper sub-section to play. \n<img width=\"451\" alt=\"Sub Menus\" src=\"https://user-images.githubusercontent.com/18543749/90851180-ebffa300-e341-11ea-85ec-35b1ad7a7395.png\">\n\n### Have you cached the videos you want to play?\n\n1. Open Aerial in System Preferences \n2. Click on the `On Rotation` tab in the sidebar (at the top)\n3. Click ‘Download rotation’ on the top right (or right click on `On Rotation` in the sidebar and click `Cache missing videos`\n\n<img width=\"220\" alt=\"Download rotation\" src=\"https://user-images.githubusercontent.com/18543749/90851831-db502c80-e343-11ea-865d-5b8a8cbecac6.png\">  <img width=\"220\" alt=\"Cache Missing Videos\" src=\"https://user-images.githubusercontent.com/18543749/90851994-4ef23980-e344-11ea-9b52-fd0fa783a10b.png\">\n\n<hr>\n\n## My Cache is too large/small\n\nAerial can cache videos in two different ways:\n- *Manually* \n- *Automatically*\n\nWhen caching is set to **manual** you will need to download and manage your cache entirely manually. When set to **automatic**, you can set the size of your cache and Aerial will fill it with the videos you love! \n\n<h3> Manual Cache Management</h3>\n\n1. Open Aerial in System Preferences \n2. Click on the settings tab (gear at the top of the sidebar)\n3. Click on `Cache` on the sidebar\n4. Uncheck 'Automatically download videos` \n<img width=\"400\" alt=\"Manual management\" src=\"https://user-images.githubusercontent.com/18543749/90852090-9678c580-e344-11ea-8f9f-7e6e3868778c.png\">\n\n5. Now download any videos you want to cache manually. \n6. Note that this may take up a significant amount of disk space. To delete or prune your cache, click the `Show in Finder` button and delete any videos you no longer want. \n\n### Automatic Cache Management\n1. Open Aerial in System Preferences \n2. Click on the settings tab (gear at the top of the sidebar)\n3. Click on `Cache` on the sidebar\n4. Check 'Automatically download videos` \n<img width=\"400\" alt=\"Automatic management\" src=\"https://user-images.githubusercontent.com/18543749/90852209-e35c9c00-e344-11ea-9505-481789a581d7.png\">\n\n5. Set your **cache limit size** - This is the *MAXIMUM* size you want your cache. If you don't want to set a maximum, move the slider all the way to the right.\n6. Select how often you want to rotate your videos in your cache \n\n<img width=\"200\" alt=\"Rotate videos\" src=\"https://user-images.githubusercontent.com/18543749/90852283-14d56780-e345-11ea-9ec5-7817cefc1d04.png\">\n\n> **NOTE:** if you have fewer videos selected than your cache size limit, videos will not rotate. If your cache is larger than your limit, then over the course of the selected time period your cache will be automatically pruned until you are under your cache limit and then videos will periodically rotate) \n\n<hr>\n\n## What video format should I select?\n\nThis can be a complicated question, however we have written about it extensively [here](https://github.com/JohnCoates/Aerial/blob/master/Documentation/HardwareDecoding.md). \n\nThe short answer is: \n- If you have an older Mac (2011-2014) you should use 1080 H.264. \n- If your Mac is 2015-2017 consider use of 1080 HEVC. \n- If you have a newer Mac (Late 2017-present) you can consider using 1080 HEVC, HDR, or, if you have more than 8GB of RAM you can give 4K a shot! \n> **NOTE:** 4K HDR requires the most intensive processing and requires a HDR compatible monitor.\n\n#### To change the format of your videos:\n\n*Skip to step 4 if you have not downloaded any videos yet*\n\n1. If you have previously downloaded/cached videos please open Aerial Settings and click on \"Advanced\" in the sidebar. Click on \"Show Log in Finder\" \n\n<img width=\"500\" alt=\"Cache Access\" src=\"https://user-images.githubusercontent.com/18543749/90925120-bcdb4700-e3be-11ea-92a4-93c79756aab2.png\">\n\n2. Inside this folder, click on the `Cache` folder \n3. Keep the folder, but delete all content inside. Then empty your trash. \n4. Go to Aerial > Settings > Advanced\n5. Select your preferred video format\n\n<img width=\"200\" alt=\"Screen Shot 2020-08-21 at 3 00 11 PM\" src=\"https://user-images.githubusercontent.com/18543749/90925319-05930000-e3bf-11ea-8027-b555c178f931.png\">\n\n6. Close and relaunch System Preferences. \n7. Open Aerial Settings again and select the videos you want. Then download (cache) these videos and they will download in the selected format.\n\n<hr>\n\n<h2>What is \"Download Rotation\" and should I click it?</h2>\n\nThe `Download Rotation` button is visible under the `On Rotation` tab on the left. \n\n<img width=\"400\" alt=\"Download Rotation\" src=\"https://user-images.githubusercontent.com/18543749/90960980-962b1800-e473-11ea-8224-d9fe1907c14e.png\">\n\nVideos in Aerial only play when they are cached on your computer. This allows them to play while you are not connected to the internet and always play immediately when your screen saver starts. \n\n> Previous versions of Aerial could \"stream\" videos without downloading a cache, but this was replaced in 2.0 with the automatic cache management tool. \n\nThe download rotation button is synonomous with saying \"Cache my rotation\". In other words, any videos in the `On Rotation` category on the left hand panel will begin to download to your computer when you click `Download Rotation`. \n\n> <b>NOTE:</b> Only videos that are cached AND that are shown in the `On Rotation` tab will play when you start your screen saver. \n\nIn the event that you want to download videos from a specific category (for example if you want to select only certain videos to play) you can additionally right click on any category and select \"Cache missing videos\" \n\n> <b>NOTE:</b> If this option is not available, it is because you have already downloaded these videos!\n\n<img width=\"200\" alt=\"Cache Missing Videos\" src=\"https://user-images.githubusercontent.com/18543749/90961135-c32bfa80-e474-11ea-8cf1-dd2abcc2d817.png\">\n\n<hr>\n\n<h2> Where is tvOS 11 and 12?</h2>\n\nAll the videos are still available in Aerial, don't worry!\n\nAerial 2.0 takes advantage of the latest available videos from tvOS. tvOS 11 and 12 are not shown as tvOS 13 actually contains these videos! \n\ntvOS 10 videos support <b>1080p</b> quality while tvOS 13 can support <b>4K</b> and <b>4K HDR</b> videos. You can still play videos from tvOS 13 in <b>1080p</b> as well. \n\n<img width=\"150\" alt=\"tvOS\" src=\"https://user-images.githubusercontent.com/18543749/90963789-e2348780-e488-11ea-859f-8a01dfa8d3fb.png\">\n\n<hr>\n\n<h2> I have more technical questions...</h2>\n\nThis FAQ was made largely to help those who are new to Aerial and GitHub. If you have more technical questions you need answered, please visit our Additional Documentation avaialble <a href=\"https://github.com/JohnCoates/Aerial/tree/master/Documentation#welcome-to-aerials-documentation\">here</a>\n\n"
  },
  {
    "path": "Documentation/HardwareDecoding.md",
    "content": "# Which format should I pick ? \n\nYou have a choice of video formats, which you can set as a preference in Settings/Advanced: 1080p H264; 1080p HEVC; 1080p HDR; 4K HEVC; or 4K HDR. At install, Aerial will suggest what it thinks is the best choice for your machine, but you can override it.\n\nThey're listed in rough order of increasing quality, and you can check below about any constraints your set-up may present (just in general, if you see stuttering - non-smooth videos - choose a lower format). Some users dislike HDR, and find its colors unrealistic, so it's probably safer to choose HEVC, but, if you're curious, or are the lucky owner of a Pro Display XDR, choose HDR and see what you think!\n\n# About HEVC and hardware decoding, and HDR\n\nAerial uses Apple's [AVFoundation framework](https://developer.apple.com/documentation/avfoundation) to play the videos as your screen saver. When available, AVFoundation will use hardware decoding (from your CPU or your graphics card) to minimize the resources needed for video playback. You can find guidelines in the help button next to the `Preferred video format` setting. By default, Aerial uses 1080p H.264 videos which is the most compatible format. Please note that all 4K HEVC videos are encoded with the `Main10` profile, which may not be hardware accelerated by your machine, while some other HEVC videos (encoded in `Main` profile) will be.\n\nWhile we wish to provide everyone with the best setting for their machine, the GVA framework from Apple doesn't let us distinguish HEVC `Main10` profile acceleration from general HEVC acceleration. Early feedback we gathered also seems to point that on machines with multiple decoding options (Intel QuickSync and AMD UVD), QuickSync will always be preferred (even if you \"force\" the discrete GPU use with an external monitor or via code, as of macOS Mojave).\n\nThese are our recommendations so far:\n\n- Macs older than 2011 may lack H.264 acceleration.\n- Macs with an Intel CPU (With iGPU) from the Sandy Bridge (2011) generation to Broadwell (Early 2015) should have H.264 hardware acceleration available.\n- Late 2015 and 2016 Macs (Skylake and Kaby Lake) may only have partially accelerated HEVC decoding. We recommended you stick to 1080p H.264 on laptops. You may consider the HEVC format on desktops but understand that decoding may be CPU intensive and spin up your fans.\n- Macs 2017 and up should have full HEVC acceleration (the 2017 12 inch Macbook being a notable exception, only having partially accelerated HEVC decoding).\n\nYou can easily check for yourself what to expect by opening a video in Quicktime (Use the `Show in Finder` option in the `Cache` tab to find the cached videos). In Activity Monitor, the AV Framework GVA process is called `VTDecoderXPCService`.\n\n# About macOS versions\n\nBecause we use Apple's Framework, what is supported will depend on the version of macOS you use.\n- You need at least macOS 10.13 to play HEVC videos\n- You need at least macOS 10.15 to play HDR videos \n\n"
  },
  {
    "path": "Documentation/Installation.md",
    "content": "# Installation, setup and uninstallation\n\n## Installation instructions\n\nAerial now includes an auto-update mechanism using the [Sparkle open-source project](https://github.com/sparkle-project/Sparkle) (with EdDSA signatures). You will need to download it manually the first time :\n\n### First Installation\n\n_Rather install from Terminal? Look at the Brew Cask section below!_\n\n1. Quit **System Preferences**.\n2. [Download the latest release of Aerial.saver.zip](https://github.com/JohnCoates/Aerial/releases/latest). Alternatively, you can try the latest beta version [following this link](https://github.com/JohnCoates/Aerial/releases). \n3. Unzip the downloaded file (if you use Safari, it should already be done for you).\n4. Double-click `Aerial.saver`; it will open in `System Preferences` > `Desktop & Screen Saver` and ask you if you want to install for all users or for your user only. Be aware that installing for all users will require a password at install **and each subsequent update, including auto-updates.**\n\nIf you see an error message saying \"This app is damaged and can't be opened, you should move it to the trash\", we suggest that **you download the file with Safari**, to prevent macOS Gatekeeper from throwing that error. Note that some outdated unzip software may cause that issue too.\n\n**Important**: If you haven't quit System Preferences before installation, you will need to quit and reopen System Preferences after installation for Aerial to work correcly. This is a macOS bug. \n\n### Brew Cask Support\n\nIf you're looking to install Aerial across many systems, remotely, or simply from Terminal we recommend [Brew Cask](https://caskroom.github.io). \n\nSimply issue the following Terminal command:\n\n```sh\nbrew install --cask aerial\n```\n\nTo upgrade Aerial, run the following Terminal command:\n\n```sh\nbrew upgrade --cask aerial\n```\n\nPlease note that if you prefer using homebrew to update Aerial, we recommend you disable Sparkle auto updates in the `Updates`tab. \n\n**Warning** If you see that your settings aren't saved in Catalina, please check if this folder exists : You may need to create this folder manually : `~/Library/Containers/com.apple.ScreenSaver.Engine.legacyScreenSaver/Data/Library/Preferences/ByHost/`\n\nYou may need to manually create the ByHost folder manually as Catalina may not do so for you.\n\n## Setting Aerial as Your Screen Saver\n\n1. Open `System Preferences` -> `Desktop & Screen Saver` -> `Screen Saver`\n2. Choose Aerial and click on `Screen Saver Options` to select your settings.\n\n![screen shot 2018-10-29 at 13 17 23](https://user-images.githubusercontent.com/37544189/47649971-1f76a980-db7f-11e8-97be-d1f90b943c9d.png)\n\n## Uninstallation\n\nThere are three ways to uninstall Aerial from your Mac. However please first read the \"Removing the cache\" section below.\n\n- Right-click on the Aerial screen saver in `System Preferences` and select `Delete \"Aerial\"`. This will uninstall the screen saver automatically.\n- If you prefer, you can delete the files manually. macOS can store screen savers in two locations depending on your choices, `/Library/Screen Savers` (if you installed for All Users) and `/Users/YOURUSERNAME/Library/Screen Savers` (installed for your user only). Check both locations for a file called `Aerial.saver` and delete any copies you find.\n- If you installed Aerial using Brew Cask, then enter the following command in a Terminal window to uninstall:\n\n```sh\nbrew uninstall --cask aerial\n```\n\n# Removing the cache \n\nAerial stores your videos in a local cache on your machine. It's location depends on the version of macOS you used, how you installed Aerial (for one user or multiple user) and when you first installed Aerial. You can find the location of the cache prior to uninstalling by going into Aerial's `Caches` tab.\n\nPrior to macOS Catalina (10.15), the cache for multiple user was either :\n- `/Library/Caches/Aerial` (long time users)\n- `/Library/Application Support/Aerial` (if you installed for the first time after summer 2019)\n\nPrior to macOS Catalina (10.15), the cache for a single user was either : \n- `~/Library/Caches/Aerial` (long time users)\n- `~/Library/Application Support/Aerial` (if you installed for the first time after summer 2019)\n\nStarting with macOS Catalina (10.15), each user has a cache in it's own sandbox at this location : \n- `~/Library/Containers/com.apple.ScreenSaver.Engine.legacyScreenSaver/Data/Library/Application Support/Aerial`\n\nFinally, the preference file is located either at :\n- `~/Library/Preferences/ByHost/com.JohnCoates.Aerial.{UUID}.plist` (before Catalina)\n- `~/Library/Containers/com.apple.ScreenSaver.Engine.legacyScreenSaver/Data/Library/Preferences/ByHost/com.JohnCoates.Aerial.{UUID}.plist` (starting with Catalina)\n\n"
  },
  {
    "path": "Documentation/MoreVideos.md",
    "content": "# Community Videos \n \nThe videos below have been shared with the project by artists, so they can be enjoyed in Aerial by everyone. \n\n## From Joshua Michaels & Hal Bergman\n\n### Series 1\n<p align=\"center\">\n  <a href=\"https://vimeo.com/449330833/36becf3668\">\n  <img src=\"https://user-images.githubusercontent.com/37544189/90661757-d7d77b00-e247-11ea-8b92-7301c39bfced.jpg\">\n  </a>\n</p>\n\nTwenty videos kindly shared by Joshua Michaels & Hal Bergman. If you enjoyed them and want to support them, please check out the packs they created specifically for Aerial below. \n\n##### Note\nIf you are an artist or a tourism association that want to share videos, check out this page here for more information : https://github.com/glouel/AerialCommunity\n\n# Online Sources\n\n## From Joshua Michaels & Hal Bergman\n\n### Note\n\nA bundle including the packs listed below is [available here](https://www.jetsoncreative.com/aerial-expansions/bundle) at a discounted price.\n\n<hr>\n\n### Cityscapes Air\n<p align=\"center\">\n  <a href=\"https://www.jetsoncreative.com/aerial-expansions/cityscapes\">\n  <img src=\"https://user-images.githubusercontent.com/37544189/90627411-2d962e00-e21c-11ea-8b65-433e558711ad.jpg\">\n  </a>\n</p>\n\n\nIncludes 50 Aerial Cityscape videos 20-60 seconds in length each in full 4K resolution.\n\nLocations include London, Brighton, Miami, Orlando, Los Angeles, Santa Monica, San Francisco, Birmingham, Flagstaff, Tuscon, Oklahoma City, Tulsa, Portland, Memphis, El Paso, Houston, and San Antonio.\n\n<hr>\n\n### Countryside Air\n<p align=\"center\">\n  <a href=\"https://www.jetsoncreative.com/aerial-expansions/countryside\">\n  <img src=\"https://user-images.githubusercontent.com/37544189/90627401-2bcc6a80-e21c-11ea-9703-19ddafd71716.jpg\">\n  </a>\n</p>\n\nIncludes 50 Aerial Countryside videos 20-60 seconds in length each in full 4K resolution.\n\nLocations include Montgomery, Glenburn, Mendocino, Gaps Crown VIneyard, Sierra Mar Vineyard, Chesterfield, Lancashire, Monsal Head, Haworth, Leeming, Wycoller, Yorkshire, Haworth, Herford, Besalu, Castellfullit, Fortia, Oberhofen, Pecos, Cocking, Little Linford, Oxenhope, Peak District, Grassington, Genola, and Chewelah.\n\n<hr>\n\n### Naturescapes Air\n<p align=\"center\">\n  <a href=\"https://www.jetsoncreative.com/aerial-expansions/naturescapes\">\n  <img src=\"https://user-images.githubusercontent.com/37544189/90627408-2cfd9780-e21c-11ea-9c3f-36416e5308d9.jpg\">\n  </a>\n</p>\n\nIncludes 50 Aerial Naturescape videos 20-60 seconds in length at full 4K resolution.\n\nLocations include Big Sur, Catalina Island, Monument Valley, Alabama Hills, Angeles Crest, Gold Lake, Lake Shasta, Shelter Cove, Sonoma, Sonora Pass, Berthound Pass, Wolf Creek Pass, Babcock Reserve & Groves, Greyton Beach, Florida Savannas & Glades, Pascagoula River, Kootenai River, Cape Lookout, Hose Rock, Lone Ranch Beach, Interlaken, Oberhofen, Bryce Canyon, Castle Valley, Eagle Canyon, Grand Staircase Escalante, Stevens Pass, and Zion.\n\n##### Note \n\nCheck out [the instructions here](https://github.com/glouel/AerialCommunity/blob/master/CreatingASource.md) on how to create your own video sources. And drop us a line if you want to be featured here!\n\n# Local sources\n\nAerial can also play videos that are on your machine. Rule of thumb is, if QuickTime can play it, Aerial can. There are a few complexities surrounding Catalina and Big Sur, because of sandboxing changes and security improvements in macOS. As a result, you cannot add videos from the \"likely\" location you'd want to use (Downloads, Desktop, Documents) and it's highly recommended to use a \"safe location\" like `/Users/Shared/`. Local sources are not supported in the current 2.0.0 build but will be back soon. In the meantime, check [those instructions, for use in version 1.9.2](https://github.com/JohnCoates/Aerial/blob/master/Documentation/CustomVideos.md).\n"
  },
  {
    "path": "Documentation/OfflineMode.md",
    "content": "#  Offline Mode\n\nIf you want to use Aerial on a Mac behind a firewall or with no network access, the easiest way starting is to copy the content of the cache folder from another Mac where Aerial is already installed.\n\nIf that's not an option, you can manually recreate a cache folder by downloading files manually. This is how to download ALL videos. \n\n# Automated version (needs a terminal)\n\nAssuming you are using a Mac and have homebrew installed (if not use your package manager of choice on your system), install wget and jq : \n\n```\nbrew install jq\nbrew install wget\n```\n\nThen it's super easy, move to the location where files should be downloaded :\n\n`cd ~/Library/Containers/com.apple.ScreenSaver.Engine.legacyScreenSaver/Data/Library/Application Support/Aerial/`\n\nThen simply do, for 4K SDR videos from tvOS12 :  \n\n`cat entries.json | jq -r '.assets[].\"url-4K-SDR\"' | xargs wget -nc -i`\n\n(this will obviously take a while 😅) \n\nReplace `url-4K-SDR` with `url-1080-H264` or `url-1080-SDR` for 1080p H264 (default) or 1080p HEVC (and `url-4K-HDR` for 4K HDR). \n\n# Manual version\n\nWe recommend you start with the first one, consider the others optional : \n\n- Download and untar `https://sylvan.apple.com/Aerials/resources-16.tar` (tvOS16 resources), unzip the `.tar` file and find the `entries.json` file.\n- Optionnally, also download and untar `https://sylvan.apple.com/Aerials/resources.tar` (tvOS12 resources), rename the bundle to `TVIdleScreenStrings12.bundle` and the JSON to `tvos12.json`.\n- Optionnally, also download and rename `https://sylvan.apple.com/Aerials/2x/entries.json` to `tvos11.json` (tvOS11 resources, also in 4K)\n- Optionnally, also download and rename `http://a1.phobos.apple.com/us/r1000/000/Features/atv/AutumnResources/videos/entries.json` to `tvos10.json` (The original Aerials, in 1080p H.264 only)\n\nYou can then download the videos you want from the JSON files. In the 4K JSONs, you are looking for the `url-1080-H264` (1080p H.264, most compatible format), `url-1080-SDR` (1080p HEVC, better quality, requires a recent Mac for hardware decoding) or `url-4K-SDR` (4K HEVC). If you want to download the HDR versions, you can but please note that they will only play in Catalina, and a recent/fast Mac is heavily recommended. \n\nPlease try to download the videos in the order mentionned (tvOS13 first) as videos routinely gets replaced with better versions. Because you will be downloading files manually, you will end up with many duplicate versions of the same videos. You can clean them up by going into the `Advanced` tab and use the `Trash old videos` feature there. You can find more information about the process [in this issue](https://github.com/JohnCoates/Aerial/issues/781#issuecomment-493677816)\n"
  },
  {
    "path": "Documentation/README.md",
    "content": "#  Welcome to Aerial's documentation\n\nThis documentation is still a work in progress, if you have any further question don't hesitate to post an issue. \n\n\n- [Frequently Asked Questions](FAQs.md)\n\n- [Troubleshooting information](Troubleshooting.md)\n\n- [Aerial's Change log](ChangeLog.md)\n\n- [Information on compiling Aerial and contributing code](Contribute.md)\n\n- [Offline mode and no network access.](OfflineMode.md)\n\n- [HEVC, HDR and hardware decoding](HardwareDecoding.md) \n\n- [How to add your own videos to Aerial](CustomVideos.md)\n\n- [Auto-updates](AutoUpdates.md)\n"
  },
  {
    "path": "Documentation/Troubleshooting.md",
    "content": "# Troubleshooting\n\n**Are you using Little Snitch or another firewall ?** Aerial requires network access for it to work, and default Little Snitch settings may impair some or all of it's features. Usually, downloading videos will be ok with default settings but you may see issues with :\n\n- Updates/auto-updates : Aerial does periodically check for new versions using Sparkle. The feed is hosted in this github repository, but access is usually denied. You may need to explicitely allow access to \"raw.githubusercontent.com\". For Catalina, you'll need to create the following rule : \n\n![Screen Shot 2020-06-05 at 12 11 52 PM](https://user-images.githubusercontent.com/28914268/83914406-056f5680-a726-11ea-905d-821ccabd0469.png)\n\n- Weather : Aerial uses Yahoo Weather's API, and requires access to it. You may need to explicitely create the following rule to get it working:\n\n![Screen Shot 2020-06-05 at 11 49 58 AM](https://user-images.githubusercontent.com/28914268/83912708-2a15ff00-a723-11ea-844d-9f6b9b18fbe8.png)\n\nIf you want to use \"Color icons\", you will need to setup this additional rule: \n\n![Screen Shot 2020-06-05 at 12 12 00 PM](https://user-images.githubusercontent.com/28914268/83914411-06a08380-a726-11ea-8f03-58400ce5a4a7.png)\n\nIn Catalina, Aerial (like all third party screensavers) is hosted by \"legacyScreenSaver.appex\". In older macOS versions, it can be hosted either by System Preferences (for the control panel) or \"ScreenSaverEngine.app\". \n\n## macOS Catalina specific issues\n\n- The sandboxing restrictions make it impossible, as far as we understand, for a screensaver file to auto-update itself, as Aerial did in the past through Sparkle. Technically speaking, you will still be prompted to install new updates, and the updates will look like they install, except the installation will silently fail. You can in the meantime either :\n  - Update manually\n  - Consider using homebrew\nAnother solution would be to have a separate updater app, which is something that will hopefully be provided soon. You can follow the progress on this in this issue : https://github.com/JohnCoates/Aerial/issues/909\n- Custom videos location : In Catalina, while it's possible to add videos that are stored in your user's Documents or Downloads folder, these files will not playback when Aerial is running as a screensaver. This is a sandboxing restriction, we recommend that you place your videos in a \"less protected\" folder such as `/Users/Shared/`.\n- Settings aren't saved : Some users (using MDM management software and/or Homebrew) seem to have run into an issue where macOS Catalina didn't create the folder where Aerial saves its preferences. You may need to create this folder manually : `~/Library/Containers/com.apple.ScreenSaver.Engine.legacyScreenSaver/Data/Library/Preferences/ByHost/`\n- Some current (or wanted/upcoming) features that require specific privileges are no longer working/impossible because of restrictions, this includes `Right arrow key to skip`.\n\n## Issues on macOS 10.14 and earlier\n\n- If you enable Weather, or Adapting videos that shows based on time, you may encounter, when exiting the screen saver, this nagging panel that doesn't disappear despite clicking Allow :\n\n![Messages_Image3499576739](https://user-images.githubusercontent.com/37544189/90182726-b6dbd980-ddb2-11ea-9a09-c5ed3efb1b48.png)\n\nIf that is the case, you can simply fix it following these instructions : \n\n+ Open System Preferences and go into Security & Privacy: \n![Capture d’écran 2020-08-13 à 20 51 31](https://user-images.githubusercontent.com/37544189/90182715-b4797f80-ddb2-11ea-9174-a02471505876.jpg)\n\n+ Then click on the `Privacy` tab and in order, click the green, orange and red circles :\n![Capture d’écran 2020-08-13 à 20 52 46](https://user-images.githubusercontent.com/37544189/90182721-b5aaac80-ddb2-11ea-9edc-b0a400159dd1.jpg)\n\nThis will allow Aerial to use your location to calculate sunset and sunrise times, and if you enabled it, provide your current weather conditions.\n\n## Very common issues/macOS bugs\n\n- \"You cannot use the Aerial screen saver with this version of macOS.\" error, or you don't see a preview and the prefererences button is greyed out: Select Aerial, close `System Preferences` with Aerial still selected, re-open System Preferences and Aerial should now work. This is a known bug with Swift screen savers in macOS/OS X reported (a long time ago...) to Apple as [rdar://25569037](http://www.openradar.me/25569037).\n- Some videos may not download, or you are seeing an error with \"A server with the specified hostname could not be found.\". This may be an issue with Content Caching in macOS, please check that link for more details and how to fix it : https://apple.stackexchange.com/questions/354197/macos-mojave-software-update-error-a-server-with-the-specified-hostname-could/371591#371591\n- Screensaver hangs at start once a day or so, or unable to quit screensaver. Users of third party firewalls like Little Snitch have reported that it may interact by either blocking by default or popping a window while Aerial tries to connect (for update or download purposes). Please either disable \"Auto update while the screen saver is running\" in Advanced tab, or allow the connexion in your firewall to `raw.githubusercontent.com` in order to fix the issue. Aerial uses the [Sparkle](https://sparkle-project.org) open source project to provide automatic updates. This works by accessing a file hosted in this repository that you can see here : `https://github.com/JohnCoates/Aerial/blob/master/appcast.xml` (Aerial accesses this url to be exact which is the \"raw\" version of the file : `https://raw.githubusercontent.com/JohnCoates/Aerial/master/appcast.xml`)\n- \"This app is damaged and can't be opened, you should move it to the trash\" when double-clicking the `Aerial.saver` file: Please see the [installation notes](Installation.md), this is a GateKeeper issue.\n- Chrome complains that \"This download is uncommon and potentilally malicious\" on very fresh releases. Google seems to flag very recent files as \"uncommon\" and may block the download (more info on [Google's site here](https://support.google.com/chrome/answer/6261569). After a few hours/days, this warning will disappear. More info in this [issue](https://github.com/JohnCoates/Aerial/issues/759#issuecomment-489616050).\n- Can't use Aerial as a login screen saver: As far as we know, using 3rd party screen savers before login is no longer possible on modern versions of macOS (probably and rightly so for security reasons). More about this [here](https://github.com/JohnCoates/Aerial/issues/571).\n- Videos are stuttering: There are thread general causes of stuttering\n  + Streaming: We heavily recommend you cache your videos instead of streaming. Streaming performance may cause stuttering or hanging as this is not something that's officially supported by the servers. \n  + HDR playback: Playback of HDR videos may cause random stuttering on some Macs, this issue has been reported on Macs with AMD graphics, and 2015 and earlier Macs with Intel graphics.\n  + Background tasks: MacOS may start some background tasks while the screensaver is running (usually after a set amount of time, like 5 minutes). `mediaanalysisd` is known to cause issues on some machines with integrated graphics. You can find more information on how to disable it here : https://github.com/JohnCoates/Aerial/issues/882#issuecomment-552104067\n\n## About custom videos\n\n- After playing a video, Aerial is stuck on the last frame for a while and does not go to the next video : Please check that your video contains correct duration information. Some export tools may generate incorrect video files and Aerial will not be able to properly detect the end of the file. To fix your files, you will need to \"remux\" them using a tool such as Handbrake or MP4Box.\n\n## About video caching\n\n- Change cache location : Starting with Catalina, and because of the sandboxing limitations introduced with macOS 10.15, Aerial will use two distinct folders. Because of the sandbox, Aerial can **only** write inside the sandbox. You can however still specify a secondary cache location, this is what the cache location is about. This is a read-only folder where you can move your videos if you wish. You need to do this manually, changing the cache location **will not** move your videos as Aerial cannot write outside the sandbox. Please note that locations outside the main disk (including networked and external drives) are not allowed. This, again, is a macOS 10.15 limitation that we can't workaround.  \n- Videos keeps disappearing, Aerial may not restart once in a while: Aerial stores all it's data in a Cache folder. This cache may get deleted by some third party software trying to free disk space. If you use such a \"Cleaning\" tool, we recommend you set a manual folder location in the Cache tab of Aerial. For example, you can create an Aerial folder in your User folder, and point to it. This will ensure Aerial files don't get deleted.\n- Black screen: If you are behind a firewall (Like Little Snitch or Hands Off!) try creating exceptions for Aerial to allow it access to Apple's servers. Be sure the applications `ScreenSaverEngine.app` and `System Preferences.app` are not being blocked access to `*.phobos.apple.com`, `*.phobos.apple.com.edgesuite.net` and `sylvan.apple.com`. If that isn't an option, please look at the [Offline mode](OfflineMode.md) documentation.\n\n## Bugs related to old versions\n*Tip : you can see the version number in the bottom right corner of the preference panel. If you don't see a version number, your version is SEVERELY outdated (1.2 or below)!*\n\n- \"Done\" button doesn't close Aerial: Please update to latest available version, this is a bug on Mojave with very old versions of Aerial (1.2 and below).\n- Not seeing extended descriptions: Make sure you have version 1.4.2 or above.\n- Can't type into text fields with macOS High Sierra/Video corruption issue on High Sierra: Please make sure you have at least version 1.4.5.\n- Aerial logs you out of your user account everytime it starts: This looks like a new bug with macOS 10.14.5 beta 18F108f (similar to the Video corruption issue on High Sierra above), possibly only for Macs with Intel graphics. Please update to Aerial 1.5.0. More information here : https://github.com/JohnCoates/Aerial/issues/738\n\n## Misc.\n\n- Brightness control does not control external displays: Aerial uses the brightness API from macOS to change the brightness of your screens. As of version 1.5.0, this does not allow us to control the brightness of external screens.\n- High CPU usage/fan spinning all of a sudden: If you correctly configured the preferred video format [according to your Mac](HardwareDecoding.md) and still experience high CPU usage/fan spinning all of a sudden, please look for the cause with `Activity Monitor`, you may see a `com.apple.photos.ImageConversionService` responsible for this CPU load. This is the iCloud Photos process, you can find more about [what it does here](https://support.apple.com/en-gu/HT204264) and how to pause it.\n\n"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2015 John Coates\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "Makefile",
    "content": ".DEFAULT_GOAL := default\n\nXCODEBUILD := xcodebuild\nBUILD_FLAGS = -scheme $(SCHEME)\n\nSCHEME ?= $(TARGET)\nTARGET ?= AerialApp\n\nclean:\n\t$(XCODEBUILD) clean $(BUILD_FLAGS)\n\nbuild: clean\n\t$(XCODEBUILD) build $(BUILD_FLAGS)\n\ntest: clean\n\t$(XCODEBUILD) test $(BUILD_FLAGS) -enableCodeCoverage YES\n\ntest-travis: clean\n\t$(XCODEBUILD) test -workspace Aerial.xcworkspace $(BUILD_FLAGS) -enableCodeCoverage YES CODE_SIGNING_ALLOWED=NO\n\nlint:\n\t@echo SwiftLint Version: $(shell swiftlint version)\n\t@echo PWD: $(shell pwd)\n\t@swiftlint lint --reporter json --strict\n\nlint-autocorrect:\n\tswiftlint autocorrect\n\nxcode-lint:\n\tswiftlint lint --lenient\n\ndefault: bootstrap\n"
  },
  {
    "path": "Podfile",
    "content": "# Uncomment the next line to define a global platform for your project\nplatform :macos, '10.9'\n\ntarget 'Aerial' do\n  # Comment the next line if you're not using Swift and don't want to use dynamic frameworks\n  use_frameworks!\n\n  # Pods for Aerial\n  pod 'Sparkle'\n\n  target 'Aerial Tests' do\n    inherit! :search_paths\n    # Pods for testing\n  end\nend\n\ntarget 'AerialApp' do\n  # Comment the next line if you're not using Swift and don't want to use dynamic frameworks\n  use_frameworks!\n\n  # Pods for AerialApp\n  pod 'Sparkle'\n  \n\nend\n\npost_install do |installer|\n    # Sign the Sparkle helper binaries to pass App Notarization.\n    system(\"codesign --force -o runtime -s 'Developer ID Application: Guillaume Louel (3L54M5L5KK)' Pods/Sparkle/Sparkle.framework/Resources/Autoupdate.app/Contents/MacOS/Autoupdate\")\n    system(\"codesign --force -o runtime -s 'Developer ID Application: Guillaume Louel (3L54M5L5KK)' Pods/Sparkle/Sparkle.framework/Resources/Autoupdate.app/Contents/MacOS/fileop\")\nend\n"
  },
  {
    "path": "Readme.md",
    "content": "<p align=\"center\">\n  <img src=\"https://cloud.githubusercontent.com/assets/499192/10754100/c0e1cc4c-7c95-11e5-9d3b-842d3acc2fd5.gif\">\n</p>\n\n# Aerial - Apple TV Aerial Views Screen Saver\n\n![Github All Releases](https://img.shields.io/github/downloads/johncoates/aerial/total.svg?maxAge=86400)\n![GitHub contributors](https://img.shields.io/github/contributors/johncoates/aerial.svg?maxAge=2592000)\n\nAerial is a Mac screensaver (macOS 10.12 or later) based on the new Apple TV screensaver that displays the Aerial movies Apple shot over New York, San Francisco, Hawaii, China, etc. Starting with version 2.0.0, it also includes videos shared by Joshua Michaels & Hal Bergman!\n\nAerial is completely open source, so feel free to contribute to its development.\n\nThis repository is used **solely** for development.\n\nStarting with version 2.3.0, Aerial can now display current weather information *and* forecasts to your location, thanks to [OpenWeather](https://openweathermap.org). \n\n![openweather_logo](https://user-images.githubusercontent.com/37544189/115738975-d689bf80-a38d-11eb-809b-fbb019e6ed08.png)\n\nWe thank [OpenWeather](https://openweathermap.org) for their support of Open Source projects. \n\n# For downloads and instructions, please go to our new website, hosted on GitHub Page: https://aerialscreensaver.github.io\n\n> Windows user? Try [OrangeJedi/Aerial](https://github.com/OrangeJedi/Aerial) <br>\n> Linux user? Try [graysky2/xscreensaver-aerial](https://github.com/graysky2/xscreensaver-aerial/)\n\n## About Aerial \n\nAerial was started in 2015 by John Coates ([Twitter](https://twitter.com/JohnCoatesDev), [Email](mailto:john@johncoates.me))\n\nStarting with version 1.4, Aerial is maintained by [Guillaume Louel](https://github.com/glouel) ([Twitter](https://twitter.com/C_Wiz)). If you are looking to support the development of Aerial, feel free to donate using the following button :\n\n[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/A0A32385Y)\n\n\n## Compatibility\n\n- macOS Sierra (10.12) and above, natively compiled for Apple Silicon\n\n## Community\n\n- **Found a bug?** Make sure you are running the latest version and please check our [FAQ](https://aerialscreensaver.github.io/faq.html) and [troubleshooting page](Documentation/Troubleshooting.md) and [our issues](https://github.com/JohnCoates/Aerial/issues), as someone may already have reported it (a beta may be available with the fix you need). Feel free to [open an issue](https://github.com/JohnCoates/Aerial/issues/new), try to be as specific as possible.\n- **Have you fixed a bug?** Or want to implement a feature? Check instructions on how to compile Aerial and more on [contributing here](Documentation/Contribute.md).\n- **Can you translate videos names and their descriptions?** Awesome! [Read here for details](Resources/Community/Readme.md) on how to help us.\n- **Have a feature request?** [Open an issue](https://github.com/JohnCoates/Aerial/issues/new). Tell us why it would be useful, and why you and others would want it.\n- **Join our [Community Discord server](https://discord.gg/TPuA5WG)** for technical support, feature requests, and a fun time!\n\n## Multilingual Support\n\nAerial features overlay descriptions of the main geographical features displayed in the videos.\n\n![Community Strings example](https://user-images.githubusercontent.com/4295/52958947-75bd6180-3395-11e9-947f-3c77d9f41928.jpg)\n\nVideo descriptions are available in many languages (Spanish, French, Polish… [check the complete list here](Resources/Community/Readme.md)) and that is only possible thanks to the collaboration and interested work of many volunteers. To best serve the international community we've defined a translation workflow that allows any person, even with **no technical background** to help translate the descriptions.\n\nIf you want to collaborate, please [read the details here](Resources/Community/Readme.md).\n\n## License\n\n[MIT License](https://raw.githubusercontent.com/JohnCoates/Aerial/master/LICENSE)\n\n"
  },
  {
    "path": "Resources/Community/Readme.md",
    "content": "# Translations of the community strings\n\nAerial features overlay descriptions of the main geographical features displayed in its videos. This is possible thanks to the collaboration and uninterested work of many. To best serve this international community we've a translation workflow defined that allows any person, even with no technical background to help translating the descriptions.\n\nIn the following sections we explain how to collaborate in the internationalization process both as a translator and as a developer.\n\n## For translators\n\n1. Contact [@glouel](https://github.com/glouel) or [@aitor](https://github.com/aitor) to get added to the Translators team at Lokalise.\n2. Access the translations dashboard at https://lokalise.co/ and translate or update the existing strings to your language.\n3. PROFIT!\n\n## For developers\n\nThe translation workflow follows a pull mode, meaning that new strings will be defined in the Lokalise service and pulled into the project once they have been translated. The pulling process will be repeated after any changes has been made to the strings.\n\n### Setting up the project\n\n1. Contact [@glouel](https://github.com/glouel) or [@aitor](https://github.com/aitor) to get added to the Translators team at Lokalise.\n2. Use the existing configuration example file to create your local configuration\n   `cp lokalise.example.cfg lokalise.cfg`\n3. In the created file update the `Token` string with your token. To get your token visit the section `API Tokens` at https://lokalise.co/profile\n\n### Downloading/pulling translations\n\n1. Install Lokalise CLI: https://docs.lokalise.co/api-and-cli/lokalise-cli-tool\n2. Once the CLI has been installed you can pull the latest versions of each language with the following command:\n   `lokalise --config lokalise.cfg d --type json --dest Resources/Community --unzip_to Resources/Community`\n3. Commit and push the new `*.json` files to the repo.\n\n## Supported languages & Kudos\n\nThe following people has helped to improve Aerial by providing translations and text corrections. Thanks everybody!\n\n- English by [@SeanMSmith](https://github.com/SeanMSmith)\n- Spanish by [@aitor](https://github.com/aitor)\n- French by [@glouel](https://github.com/glouel)\n- Polish by [@Soruk](https://github.com/Soruk)\n- German by [@moeffju](https://github.com/moeffju)\n- Hebrew by [@kaaspad](https://github.com/kaaspad)\n- Arabic by [@kachikulu](https://github.com/kachikulu)\n- Simplified Chinese by [@LinkeyLeo](https://github.com/LinkeyLeo)\n- Japanese by [@DrMORO617](https://github.com/DrMORO617)\n\n## Sponsorship\n\n![Lokalise logo](https://user-images.githubusercontent.com/4295/52958944-73f39e00-3395-11e9-9350-79bb7ee43d14.png)\n\n[Lokalise](https://lokalise.co) supports Aerial and provides us with a free plan to make the translation of this project possible. Check it out for your next i18n project!\n"
  },
  {
    "path": "Resources/Community/ar.json",
    "content": "{\n    \"009BA758-7060-4479-8EE8-FB9B40C8FB97\": {\n        \"name\": \"كوريا واليابان في الليل\"\n    },\n    \"B1B5DDC5-73C8-4920-8133-BACCE38A08DE\": {\n        \"name\": \"مكسيكو سيتي إلى نيويورك\"\n    },\n    \"7719B48A-2005-4011-9280-2F64EEC6FD91\": {\n        \"name\": \"شمال كاليفورنيا إلى ولاية باها\"\n    },\n    \"B876B645-3955-420E-99DF-60139E451CF3\": {\n        \"name\": \"الحديقة الوطنية وليغيوان ١\"\n    },\n    \"9CCB8297-E9F5-4699-AE1F-890CFBD5E29C\": {\n        \"name\": \"مدرجات الأرز لونججي\"\n    },\n    \"D5E76230-81A3-4F65-A1BA-51B8CADED625\": {\n        \"name\": \"الحديقة الوطنية وليغيوان ٢\"\n    },\n    \"F0236EC5-EE72-4058-A6CE-1F7D2E8253BF\": {\n        \"name\": \"سور الصين العظيم 1\"\n    },\n    \"22162A9B-DB90-4517-867C-C676BC3E8E95\": {\n        \"name\": \"سور الصين العظيم 2\"\n    },\n    \"044AD56C-A107-41B2-90CC-E60CCACFBCF5\": {\n        \"name\": \"سور الصين العظيم 3\"\n    },\n    \"876D51F4-3D78-4221-8AD2-F9E78C0FD9B9\": {\n        \"name\": \"طريق الشيخ زايد\"\n    },\n    \"E991AC0C-F272-44D8-88F3-05F44EDFE3AE\": {\n        \"name\": \"مرسى ١\"\n    },\n    \"00BA71CD-2C54-415A-A68A-8358E677D750\": {\n        \"name\": \"وسط المدينة\"\n    },\n    \"3FFA2A97-7D28-49EA-AA39-5BC9051B2745\": {\n        \"name\": \"مرسى ٢\"\n    },\n    \"9680B8EB-CE2A-4395-AF41-402801F4D6A6\": {\n        \"name\": \"الإقتراب من برج خليفة\"\n    },\n    \"2F11E857-4F77-4476-8033-4A1E4610AFCC\": {\n        \"name\": \"طريق الشيخ زايد\"\n    },\n    \"B8F204CE-6024-49AB-85F9-7CA2F6DCD226\": {\n        \"name\": \"شبه الجزيرة نووسواق\"\n    },\n    \"2F52E34C-39D4-4AB1-9025-8F7141FAA720\": {\n        \"name\": \"إيسيفجورد ايلوليسات\"\n    },\n    \"EE01F02D-1413-436C-AB05-410F224A5B7B\": {\n        \"name\": \"إيسيفجورد ايلوليسات\"\n    },\n    \"499995FA-E51A-4ACE-8DFD-BDF8AFF6C943\": {\n        \"name\": \"وادي وايمانو\"\n    },\n    \"12E0343D-2CD9-48EA-AB57-4D680FB6D0C7\": {\n        \"name\": \"لاوبهويهوي نوي، هاواي\"\n    },\n    \"b2-2\": {\n        \"name\": \"وادي هونوب\"\n    },\n    \"258A6797-CC13-4C3A-AB35-4F25CA3BF474\": {\n        \"name\": \"محمية پو أو أومي الطبيعية\"\n    },\n    \"3D729CFC-9000-48D3-A052-C5BD5B7A6842\": {\n        \"name\": \"ساحل كوهالا\"\n    },\n    \"82BD33C9-B6D2-47E7-9C42-AA3B7758921A\": {\n        \"name\": \"محمية پو أو أومي الطبيعية\"\n    },\n    \"FE8E1F9D-59BA-4207-B626-28E34D810D0A\": {\n        \"name\": \"ميناء فيكتوريا ١\"\n    },\n    \"C8559883-6F3E-4AF2-8960-903710CD47B7\": {\n        \"name\": \"جبل فيكتوريا\"\n    },\n    \"024891DE-B7F6-4187-BFE0-E6D237702EF0\": {\n        \"name\": \"وان تشاي\"\n    },\n    \"64EA30BD-C4B5-4CDD-86D7-DFE47E9CB9AA\": {\n        \"name\": \"ميناء فيكتوريا ٢\"\n    },\n    \"E99FA658-A59A-4A2D-9F3B-58E7BDC71A9A\": {\n        \"name\": \"ميناء فيكتوريا\"\n    },\n    \"001C94AE-2BA4-4E77-A202-F7DE60E8B1C8\": {\n        \"name\": \"واحة ليوا ١\"\n    },\n    \"AFA22C08-A486-4CE8-9A13-E355B6C38559\": {\n        \"name\": \"واحة ليوا ٢\"\n    },\n    \"58754319-8709-4AB0-8674-B34F04E7FFE2\": {\n        \"name\": \"نهر التايمز\"\n    },\n    \"A5AAFF5D-8887-42BB-8AFD-867EF557ED85\": {\n        \"name\": \"قصر باكنغهام\"\n    },\n    \"F604AF56-EA77-4960-AEF7-82533CC1A8B3\": {\n        \"name\": \"نهر التايمز مع قرب غروب الشمس\"\n    },\n    \"7F4C26C2-67C2-4C3A-8F07-8A7BF6148C97\": {\n        \"name\": \"نهر التايمز في الغسق\"\n    },\n    \"CE279831-1CA7-4A83-A97B-FF1E20234396\": {\n        \"name\": \"مطار لوس أنجلوس الدولي\"\n    },\n    \"35693AEA-F8C4-4A80-B77D-C94B20A68956\": {\n        \"name\": \"طريق هاربور السريع\"\n    },\n    \"92E48DE9-13A1-4172-B560-29B4668A87EE\": {\n        \"name\": \"شاطئ سانتا مونيكا\"\n    },\n    \"89B1643B-06DD-4DEC-B1B0-774493B0F7B7\": {\n        \"name\": \"مرصد جريفيث\"\n    },\n    \"EC67726A-8212-4C5E-83CF-8412932740D2\": {\n        \"name\": \"تلال هوليوود\"\n    },\n    \"F5804DD6-5963-40DA-9FA0-39C0C6E6DEF9\": {\n        \"name\": \"وسط المدينة\"\n    },\n    \"3BA0CFC7-E460-4B59-A817-B97F9EBB9B89\": {\n        \"name\": \"سنترال بارك\"\n    },\n    \"b1-3\": {\n        \"name\": \"مانهاتن السفلى\"\n    },\n    \"840FE8E4-D952-4680-B1A7-AC5BACA2C1F8\": {\n        \"name\": \"الجانب الشرقي الاعلى\"\n    },\n    \"44166C39-8566-4ECA-BD16-43159429B52F\": {\n        \"name\": \"الجادة السابعة\"\n    },\n    \"640DFB00-FBB9-45DA-9444-9F663859F4BC\": {\n        \"name\": \"مانهاتن السفلى\"\n    },\n    \"b8-2\": {\n        \"name\": \"شبة الجزيرة الجبلية مارين هيدلاندز\"\n    },\n    \"EE533FBD-90AE-419A-AD13-D7A60E2015D6\": {\n        \"name\": \"مارين هيدلاندز في الضباب\"\n    },\n    \"DE851E6D-C2BE-4D9F-AB54-0F9CE994DC51\": {\n        \"name\": \"خليج سان فرانسيسكو و جسر البوابة الذهبية\"\n    },\n    \"b8-3\": {\n        \"name\": \"مربع آلامو\"\n    },\n    \"85CE77BF-3413-4A7B-9B0F-732E96229A73\": {\n        \"name\": \"امباركادرو، شارع السوق\"\n    },\n    \"b4-3\": {\n        \"name\": \"بريسيديو إلى جسر البوابة الذهبية\"\n    },\n    \"72B4390D-DF1D-4D51-B179-229BBAEFFF2C\": {\n        \"name\": \"جسر البوابة الذهبية من سان فرانسيسكو\"\n    },\n    \"b6-4\": {\n        \"name\": \"وسط المدينة وبرج كولت\"\n    },\n    \"29BDF297-EB43-403A-8719-A78DA11A2948\": {\n        \"name\": \"مرسى الصيادين\"\n    },\n    \"b5-3\": {\n        \"name\": \"امباركادرو، شارع السوق\"\n    },\n    \"3E94AE98-EAF2-4B09-96E3-452F46BC114E\": {\n        \"name\": \"جسر الخليج\"\n    },\n    \"b2-4\": {\n        \"name\": \"وسط المدينة وبرج سوترو\"\n    },\n    \"4AD99907-9E76-408D-A7FC-8429FF014201\": {\n        \"name\": \"خليج سان فرانسيسكو و امباركاديرو\"\n    },\n    \"03EC0F5E-CCA8-4E0A-9FEC-5BD1CE151182\": {\n        \"name\": \"القارة القطبية الجنوبية\"\n    },\n    \"737E9E24-49BE-4104-9B72-F352DE1AD2BF\": {\n        \"name\": \"الشفق القطبي لأمريكا الشمالية\"\n    },\n    \"A837FA8C-C643-4705-AE92-074EFDD067F7\": {\n        \"name\": \"أفريقيا في الليل\"\n    },\n    \"2F72BC1E-3D76-456C-81EB-842EBA488C27\": {\n        \"name\": \"أفريقيا والشرق الأوسط\"\n    },\n    \"12318CCB-3F78-43B7-A854-EFDCCE5312CD\": {\n        \"name\": \"كاليفورنيا إلى فيغاس\"\n    },\n    \"D5CFB2FF-5F8C-4637-816B-3E42FC1229B8\": {\n        \"name\": \"منطقة البحر الكاريبي\"\n    },\n    \"4F881F8B-A7D9-4FDB-A917-17BF6AC5A589\": {\n        \"name\": \"اليوم الكاريبي\"\n    },\n    \"7825C73A-658F-48EE-B14C-EC56673094AC\": {\n        \"name\": \"الصين\"\n    },\n    \"E5DB138A-F04E-4619-B896-DE5CB538C534\": {\n        \"name\": \"إيطاليا إلى آسيا\"\n    },\n    \"F439B0A7-D18C-4B14-9681-6520E6A74FE9\": {\n        \"name\": \"إيران وأفغانستان\"\n    },\n    \"7C643A39-C0B2-4BA0-8BC2-2EAA47CC580E\": {\n        \"name\": \"ايرلندا إلى آسيا\"\n    },\n    \"63C042F0-90EF-4A95-B7CC-CC9A64BF8421\": {\n        \"name\": \"غرب أفريقيا إلى جبال الألب\"\n    },\n    \"78911B7E-3C69-47AD-B635-9C2486F6301D\": {\n        \"name\": \"نيوزيلندا\"\n    },\n    \"E556BBC5-D0A0-4DB1-AC77-BC76E4A526F4\": {\n        \"name\": \"صحارى و إيطاليا\"\n    },\n    \"64D11DAB-3B57-4F14-AD2F-E59A9282FA44\": {\n        \"name\": \"المحيط الأطلسي إلى إسبانيا وفرنسا\"\n    },\n    \"81337355-E156-4242-AAF4-711768D30A54\": {\n        \"name\": \"استراليا\"\n    },\n    \"1088217C-1410-4CF7-BDE9-8F573A4DBCD9\": {\n        \"name\": \"منطقة البحر الكاريبي إلى أمريكا الوسطى\"\n    },\n    \"3C4678E4-4D3D-4A40-8817-77752AEA62EB\": {\n        \"name\": \"دلتا النيل\"\n    },\n    \"87060EC2-D006-4102-98CC-3005C68BB343\": {\n        \"name\": \"جنوب أفريقيا إلى شمال آسيا\"\n    },\n    \"F07CC61B-30FC-4614-BDAD-3240B61F6793\": {\n        \"name\": \"مرجان بالاو\"\n    },\n    \"6143116D-03BB-485E-864E-A8CF58ACF6F1\": {\n        \"name\": \"عشب البحر جنوب أفريقيا\"\n    },\n    \"2B30E324-E4FF-4CC1-BA45-A958C2D2B2EC\": {\n        \"name\": \"أسماك الباراكودا\"\n    },\n    \"581A4F1A-2B6D-468C-A1BE-6F473F06D10B\": {\n        \"name\": \"نجوم البحر\"\n    },\n    \"687D03A2-18A5-4181-8E85-38F3A13409B9\": {\n        \"name\": \"أسماك الروؤس المنتفخة\"\n    },\n    \"537A4DAB-83B0-4B66-BCD1-05E5DBB4A268\": {\n        \"name\": \"أسماك الشيم الحصاني\"\n    },\n    \"27A37B0F-738D-4644-A7A4-E33E7A6C1175\": {\n        \"name\": \"دلافين كاليفورنيا\"\n    },\n    \"EB3F48E7-D30F-4079-858F-1A61331D5026\": {\n        \"name\": \"غابات عشب البحر كاليفورنيا\"\n    },\n    \"CE9B5D5B-B6E7-47C5-8C04-59BF182E98FB\": {\n        \"name\": \"دلافين كوستاريكا\"\n    },\n    \"58C75C62-3290-47B8-849C-56A583173570\": {\n        \"name\": \"أسماك الغرابي المشعة\"\n    },\n    \"3716DD4B-01C0-4F5B-8DD6-DB771EC472FB\": {\n        \"name\": \"اسماك قرش الشعب الرمادية\"\n    },\n    \"DD47D8E1-CB66-4C12-BFEA-2ADB0D8D1E2E\": {\n        \"name\": \"الحوت الأحدب\"\n    },\n    \"82175C1F-153C-4EC8-AE37-2860EA828004\": {\n        \"name\": \"مرجان البحر الأحمر\"\n    },\n    \"391BDF6E-3279-4CE1-9CA5-0F82811452D7\": {\n        \"name\": \"فقمات\"\n    },\n    \"BA4ECA11-592F-4727-9221-D2A32A16EB28\": {\n        \"name\": \"قناديل بحر پالاو 1\"\n    },\n    \"E580E5A5-0888-4BE8-A4CA-F74A18A643C3\": {\n        \"name\": \"قناديل بحر پالاو 2\"\n    },\n    \"EC3DC957-D4C2-4732-AACE-7D0C0F390EC8\": {\n        \"name\": \"قناديل بحر پالاو 3\"\n    },\n    \"C7AD3D0A-7EDF-412C-A237-B3C9D27381A1\": {\n        \"name\": \"قناديل بحر الآسكا 1\"\n    },\n    \"C6DC4E54-1130-44F8-AF6F-A551D8E8A181\": {\n        \"name\": \"قناديل بحر الآسكا 2\"\n    },\n    \"149E7795-DBDA-4F5D-B39A-14712F841118\": {\n        \"name\": \"أمواج تاهيتي 1\"\n    },\n    \"8C31B06F-91A4-4F7C-93ED-56146D7F48B9\": {\n        \"name\": \"أمواج تاهيتي 2\"\n    }\n}"
  },
  {
    "path": "Resources/Community/de.json",
    "content": "{\n    \"009BA758-7060-4479-8EE8-FB9B40C8FB97\": {\n        \"name\": \"Korea und Japan bei Nacht\"\n    },\n    \"B1B5DDC5-73C8-4920-8133-BACCE38A08DE\": {\n        \"name\": \"Mexiko-Stadt nach New York\"\n    },\n    \"7719B48A-2005-4011-9280-2F64EEC6FD91\": {\n        \"name\": \"Nordkalifornien nach Baja\"\n    },\n    \"B876B645-3955-420E-99DF-60139E451CF3\": {\n        \"name\": \"Wulingyuan Nationalpark 1\"\n    },\n    \"9CCB8297-E9F5-4699-AE1F-890CFBD5E29C\": {\n        \"name\": \"Longji Reisterrassen\"\n    },\n    \"D5E76230-81A3-4F65-A1BA-51B8CADED625\": {\n        \"name\": \"Wulingyuan Nationalpark 2\"\n    },\n    \"F0236EC5-EE72-4058-A6CE-1F7D2E8253BF\": {\n        \"name\": \"Chinesische Mauer 1\"\n    },\n    \"22162A9B-DB90-4517-867C-C676BC3E8E95\": {\n        \"name\": \"Chinesische Mauer 2\"\n    },\n    \"044AD56C-A107-41B2-90CC-E60CCACFBCF5\": {\n        \"name\": \"Chinesische Mauer 3\"\n    },\n    \"876D51F4-3D78-4221-8AD2-F9E78C0FD9B9\": {\n        \"name\": \"Sheikh Zayed Road\"\n    },\n    \"E991AC0C-F272-44D8-88F3-05F44EDFE3AE\": {\n        \"name\": \"Marina 1\"\n    },\n    \"00BA71CD-2C54-415A-A68A-8358E677D750\": {\n        \"name\": \"Innenstadt\"\n    },\n    \"3FFA2A97-7D28-49EA-AA39-5BC9051B2745\": {\n        \"name\": \"Marina 2\"\n    },\n    \"9680B8EB-CE2A-4395-AF41-402801F4D6A6\": {\n        \"name\": \"Anflug zum Burj Khalifa\"\n    },\n    \"2F11E857-4F77-4476-8033-4A1E4610AFCC\": {\n        \"name\": \"Sheikh Zayed Road\"\n    },\n    \"B8F204CE-6024-49AB-85F9-7CA2F6DCD226\": {\n        \"name\": \"Nuussuaq-Halbinsel\"\n    },\n    \"2F52E34C-39D4-4AB1-9025-8F7141FAA720\": {\n        \"name\": \"Ilulissat-Eisfjord\"\n    },\n    \"EE01F02D-1413-436C-AB05-410F224A5B7B\": {\n        \"name\": \"Ilulissat-Eisfjord\"\n    },\n    \"499995FA-E51A-4ACE-8DFD-BDF8AFF6C943\": {\n        \"name\": \"Waimanu-Tal\"\n    },\n    \"12E0343D-2CD9-48EA-AB57-4D680FB6D0C7\": {\n        \"name\": \"Laupāhoehoe Nui\"\n    },\n    \"b2-2\": {\n        \"name\": \"Honopū-Tal\"\n    },\n    \"258A6797-CC13-4C3A-AB35-4F25CA3BF474\": {\n        \"name\": \"Pu'u O 'Umi\"\n    },\n    \"3D729CFC-9000-48D3-A052-C5BD5B7A6842\": {\n        \"name\": \"Küste von Kohala\"\n    },\n    \"82BD33C9-B6D2-47E7-9C42-AA3B7758921A\": {\n        \"name\": \"Pu'u O 'Umi\"\n    },\n    \"FE8E1F9D-59BA-4207-B626-28E34D810D0A\": {\n        \"name\": \"Victoria Harbour 1\"\n    },\n    \"C8559883-6F3E-4AF2-8960-903710CD47B7\": {\n        \"name\": \"Victoria Peak\"\n    },\n    \"024891DE-B7F6-4187-BFE0-E6D237702EF0\": {\n        \"name\": \"Wan Chai\"\n    },\n    \"64EA30BD-C4B5-4CDD-86D7-DFE47E9CB9AA\": {\n        \"name\": \"Victoria Harbour 2\"\n    },\n    \"E99FA658-A59A-4A2D-9F3B-58E7BDC71A9A\": {\n        \"name\": \"Victoria Harbour\"\n    },\n    \"001C94AE-2BA4-4E77-A202-F7DE60E8B1C8\": {\n        \"name\": \"Liwa-Oase 1\"\n    },\n    \"AFA22C08-A486-4CE8-9A13-E355B6C38559\": {\n        \"name\": \"Liwa-Oase 2\"\n    },\n    \"58754319-8709-4AB0-8674-B34F04E7FFE2\": {\n        \"name\": \"Die Themse\"\n    },\n    \"A5AAFF5D-8887-42BB-8AFD-867EF557ED85\": {\n        \"name\": \"Buckingham Palace\"\n    },\n    \"F604AF56-EA77-4960-AEF7-82533CC1A8B3\": {\n        \"name\": \"Die Themse bei Sonnenuntergang\"\n    },\n    \"7F4C26C2-67C2-4C3A-8F07-8A7BF6148C97\": {\n        \"name\": \"Die Themse in der Abenddämmerung\"\n    },\n    \"CE279831-1CA7-4A83-A97B-FF1E20234396\": {\n        \"name\": \"Internationaler Flughafen von Los Angeles\"\n    },\n    \"35693AEA-F8C4-4A80-B77D-C94B20A68956\": {\n        \"name\": \"Harbor Freeway\"\n    },\n    \"92E48DE9-13A1-4172-B560-29B4668A87EE\": {\n        \"name\": \"Strand von Santa Monica\"\n    },\n    \"89B1643B-06DD-4DEC-B1B0-774493B0F7B7\": {\n        \"name\": \"Griffith-Sternwarte\"\n    },\n    \"EC67726A-8212-4C5E-83CF-8412932740D2\": {\n        \"name\": \"Hollywood Hills\"\n    },\n    \"F5804DD6-5963-40DA-9FA0-39C0C6E6DEF9\": {\n        \"name\": \"Innenstadt\"\n    },\n    \"3BA0CFC7-E460-4B59-A817-B97F9EBB9B89\": {\n        \"name\": \"Central Park\"\n    },\n    \"b1-3\": {\n        \"name\": \"Lower Manhattan\"\n    },\n    \"840FE8E4-D952-4680-B1A7-AC5BACA2C1F8\": {\n        \"name\": \"Upper East Side\"\n    },\n    \"44166C39-8566-4ECA-BD16-43159429B52F\": {\n        \"name\": \"Seventh Avenue\"\n    },\n    \"640DFB00-FBB9-45DA-9444-9F663859F4BC\": {\n        \"name\": \"Lower Manhattan\"\n    },\n    \"b8-2\": {\n        \"name\": \"Marin Headlands\"\n    },\n    \"EE533FBD-90AE-419A-AD13-D7A60E2015D6\": {\n        \"name\": \"Marin Headlands im Nebel\"\n    },\n    \"DE851E6D-C2BE-4D9F-AB54-0F9CE994DC51\": {\n        \"name\": \"Bucht und Golden Gate\"\n    },\n    \"b8-3\": {\n        \"name\": \"Alamo Square\"\n    },\n    \"85CE77BF-3413-4A7B-9B0F-732E96229A73\": {\n        \"name\": \"Embarcadero, Market Street\"\n    },\n    \"b4-3\": {\n        \"name\": \"Presidio zur Golden Gate\"\n    },\n    \"72B4390D-DF1D-4D51-B179-229BBAEFFF2C\": {\n        \"name\": \"Golden Gate aus Richtung San Francisco\"\n    },\n    \"b6-4\": {\n        \"name\": \"Innenstadt und Coit Tower\"\n    },\n    \"29BDF297-EB43-403A-8719-A78DA11A2948\": {\n        \"name\": \"Fisherman's Wharf\"\n    },\n    \"b5-3\": {\n        \"name\": \"Embarcadero, Market Street\"\n    },\n    \"3E94AE98-EAF2-4B09-96E3-452F46BC114E\": {\n        \"name\": \"Brücke über die San Francisco Bay\"\n    },\n    \"b2-4\": {\n        \"name\": \"Innenstadt und Sutro Tower\"\n    },\n    \"4AD99907-9E76-408D-A7FC-8429FF014201\": {\n        \"name\": \"Bucht von San Francisco und Embarcadero\"\n    },\n    \"03EC0F5E-CCA8-4E0A-9FEC-5BD1CE151182\": {\n        \"name\": \"Antarktis\"\n    },\n    \"737E9E24-49BE-4104-9B72-F352DE1AD2BF\": {\n        \"name\": \"Nordamerikanische Aurora\"\n    },\n    \"A837FA8C-C643-4705-AE92-074EFDD067F7\": {\n        \"name\": \"Afrika bei Nacht\"\n    },\n    \"2F72BC1E-3D76-456C-81EB-842EBA488C27\": {\n        \"name\": \"Afrika und der Nahe Osten\"\n    },\n    \"12318CCB-3F78-43B7-A854-EFDCCE5312CD\": {\n        \"name\": \"Kalifornien nach Vegas\"\n    },\n    \"D5CFB2FF-5F8C-4637-816B-3E42FC1229B8\": {\n        \"name\": \"Karibik\"\n    },\n    \"4F881F8B-A7D9-4FDB-A917-17BF6AC5A589\": {\n        \"name\": \"Tag in der Karibik\"\n    },\n    \"7825C73A-658F-48EE-B14C-EC56673094AC\": {\n        \"name\": \"China\"\n    },\n    \"E5DB138A-F04E-4619-B896-DE5CB538C534\": {\n        \"name\": \"Italien nach Asien\"\n    },\n    \"F439B0A7-D18C-4B14-9681-6520E6A74FE9\": {\n        \"name\": \"Iran und Afghanistan\"\n    },\n    \"7C643A39-C0B2-4BA0-8BC2-2EAA47CC580E\": {\n        \"name\": \"Irland bis Asien\"\n    },\n    \"63C042F0-90EF-4A95-B7CC-CC9A64BF8421\": {\n        \"name\": \"Westafrika bis zu den Alpen\"\n    },\n    \"78911B7E-3C69-47AD-B635-9C2486F6301D\": {\n        \"name\": \"Neuseeland\"\n    },\n    \"E556BBC5-D0A0-4DB1-AC77-BC76E4A526F4\": {\n        \"name\": \"Sahara und Italien\"\n    },\n    \"64D11DAB-3B57-4F14-AD2F-E59A9282FA44\": {\n        \"name\": \"Atlantik nach Spanien und Frankreich\"\n    },\n    \"81337355-E156-4242-AAF4-711768D30A54\": {\n        \"name\": \"Australien\"\n    },\n    \"1088217C-1410-4CF7-BDE9-8F573A4DBCD9\": {\n        \"name\": \"Karibik nach Mittelamerika\"\n    },\n    \"3C4678E4-4D3D-4A40-8817-77752AEA62EB\": {\n        \"name\": \"Nildelta\"\n    },\n    \"87060EC2-D006-4102-98CC-3005C68BB343\": {\n        \"name\": \"Südafrika nach Nordasien\"\n    },\n    \"F07CC61B-30FC-4614-BDAD-3240B61F6793\": {\n        \"name\": \"Korallen bei Palau\"\n    },\n    \"6143116D-03BB-485E-864E-A8CF58ACF6F1\": {\n        \"name\": \"Südafrikanischer Seetang\"\n    },\n    \"2B30E324-E4FF-4CC1-BA45-A958C2D2B2EC\": {\n        \"name\": \"Barrakudas\"\n    },\n    \"581A4F1A-2B6D-468C-A1BE-6F473F06D10B\": {\n        \"name\": \"Seesterne\"\n    },\n    \"687D03A2-18A5-4181-8E85-38F3A13409B9\": {\n        \"name\": \"Büffelkopf-Papageifische\"\n    },\n    \"537A4DAB-83B0-4B66-BCD1-05E5DBB4A268\": {\n        \"name\": \"Pferdemakrelen\"\n    },\n    \"27A37B0F-738D-4644-A7A4-E33E7A6C1175\": {\n        \"name\": \"Kalifornische Delfine\"\n    },\n    \"EB3F48E7-D30F-4079-858F-1A61331D5026\": {\n        \"name\": \"Kalifornischer Seetangwald\"\n    },\n    \"CE9B5D5B-B6E7-47C5-8C04-59BF182E98FB\": {\n        \"name\": \"Delfine bei Costa Rica\"\n    },\n    \"58C75C62-3290-47B8-849C-56A583173570\": {\n        \"name\": \"Atlantischer Kuhnasenrochen\"\n    },\n    \"3716DD4B-01C0-4F5B-8DD6-DB771EC472FB\": {\n        \"name\": \"Grauer Riffhai\"\n    },\n    \"DD47D8E1-CB66-4C12-BFEA-2ADB0D8D1E2E\": {\n        \"name\": \"Buckelwal\"\n    },\n    \"82175C1F-153C-4EC8-AE37-2860EA828004\": {\n        \"name\": \"Korallen im Roten Meer\"\n    },\n    \"391BDF6E-3279-4CE1-9CA5-0F82811452D7\": {\n        \"name\": \"Robben\"\n    },\n    \"BA4ECA11-592F-4727-9221-D2A32A16EB28\": {\n        \"name\": \"Quallen bei Palau 1\"\n    },\n    \"E580E5A5-0888-4BE8-A4CA-F74A18A643C3\": {\n        \"name\": \"Quallen bei Palau 2\"\n    },\n    \"EC3DC957-D4C2-4732-AACE-7D0C0F390EC8\": {\n        \"name\": \"Quallen bei Palau 3\"\n    },\n    \"C7AD3D0A-7EDF-412C-A237-B3C9D27381A1\": {\n        \"name\": \"Quallen bei Alaska 1\"\n    },\n    \"C6DC4E54-1130-44F8-AF6F-A551D8E8A181\": {\n        \"name\": \"Quallen bei Alaska 2\"\n    },\n    \"149E7795-DBDA-4F5D-B39A-14712F841118\": {\n        \"name\": \"Wellen bei Tahiti 1\"\n    },\n    \"8C31B06F-91A4-4F7C-93ED-56146D7F48B9\": {\n        \"name\": \"Wellen bei Tahiti 2\"\n    }\n}"
  },
  {
    "path": "Resources/Community/en.json",
    "content": "{\n    \"009BA758-7060-4479-8EE8-FB9B40C8FB97\": {\n        \"name\": \"Korea and Japan Night\"\n    },\n    \"B1B5DDC5-73C8-4920-8133-BACCE38A08DE\": {\n        \"name\": \"Mexico City to New York\"\n    },\n    \"7719B48A-2005-4011-9280-2F64EEC6FD91\": {\n        \"name\": \"Northern California to Baja\"\n    },\n    \"B876B645-3955-420E-99DF-60139E451CF3\": {\n        \"name\": \"Wulingyuan National Park 1\"\n    },\n    \"9CCB8297-E9F5-4699-AE1F-890CFBD5E29C\": {\n        \"name\": \"Longji Rice Terraces\"\n    },\n    \"D5E76230-81A3-4F65-A1BA-51B8CADED625\": {\n        \"name\": \"Wulingyuan National Park 2\"\n    },\n    \"F0236EC5-EE72-4058-A6CE-1F7D2E8253BF\": {\n        \"name\": \"Great Wall 1\"\n    },\n    \"22162A9B-DB90-4517-867C-C676BC3E8E95\": {\n        \"name\": \"Great Wall 2\"\n    },\n    \"044AD56C-A107-41B2-90CC-E60CCACFBCF5\": {\n        \"name\": \"Great Wall 3\"\n    },\n    \"876D51F4-3D78-4221-8AD2-F9E78C0FD9B9\": {\n        \"name\": \"Sheikh Zayed Road\"\n    },\n    \"E991AC0C-F272-44D8-88F3-05F44EDFE3AE\": {\n        \"name\": \"Marina 1\"\n    },\n    \"00BA71CD-2C54-415A-A68A-8358E677D750\": {\n        \"name\": \"Downtown\"\n    },\n    \"3FFA2A97-7D28-49EA-AA39-5BC9051B2745\": {\n        \"name\": \"Marina 2\"\n    },\n    \"9680B8EB-CE2A-4395-AF41-402801F4D6A6\": {\n        \"name\": \"Approaching Burj Khalifa\"\n    },\n    \"2F11E857-4F77-4476-8033-4A1E4610AFCC\": {\n        \"name\": \"Sheikh Zayed Road\"\n    },\n    \"B8F204CE-6024-49AB-85F9-7CA2F6DCD226\": {\n        \"name\": \"Nuussuaq Peninsula\"\n    },\n    \"2F52E34C-39D4-4AB1-9025-8F7141FAA720\": {\n        \"name\": \"Ilulissat Icefjord\"\n    },\n    \"EE01F02D-1413-436C-AB05-410F224A5B7B\": {\n        \"name\": \"Ilulissat Icefjord\"\n    },\n    \"499995FA-E51A-4ACE-8DFD-BDF8AFF6C943\": {\n        \"name\": \"Waimanu Valley\"\n    },\n    \"12E0343D-2CD9-48EA-AB57-4D680FB6D0C7\": {\n        \"name\": \"Laupāhoehoe Nui\"\n    },\n    \"b2-2\": {\n        \"name\": \"Honopū Valley\"\n    },\n    \"258A6797-CC13-4C3A-AB35-4F25CA3BF474\": {\n        \"name\": \"Pu‘u O ‘Umi\"\n    },\n    \"3D729CFC-9000-48D3-A052-C5BD5B7A6842\": {\n        \"name\": \"Kohala Coastline\"\n    },\n    \"82BD33C9-B6D2-47E7-9C42-AA3B7758921A\": {\n        \"name\": \"Pu‘u O ‘Umi\"\n    },\n    \"FE8E1F9D-59BA-4207-B626-28E34D810D0A\": {\n        \"name\": \"Victoria Harbour 1\"\n    },\n    \"C8559883-6F3E-4AF2-8960-903710CD47B7\": {\n        \"name\": \"Victoria Peak\"\n    },\n    \"024891DE-B7F6-4187-BFE0-E6D237702EF0\": {\n        \"name\": \"Wan Chai\"\n    },\n    \"64EA30BD-C4B5-4CDD-86D7-DFE47E9CB9AA\": {\n        \"name\": \"Victoria Harbour 2\"\n    },\n    \"E99FA658-A59A-4A2D-9F3B-58E7BDC71A9A\": {\n        \"name\": \"Victoria Harbour\"\n    },\n    \"001C94AE-2BA4-4E77-A202-F7DE60E8B1C8\": {\n        \"name\": \"Liwa Oasis 1\"\n    },\n    \"AFA22C08-A486-4CE8-9A13-E355B6C38559\": {\n        \"name\": \"Liwa Oasis 2\"\n    },\n    \"58754319-8709-4AB0-8674-B34F04E7FFE2\": {\n        \"name\": \"River Thames\"\n    },\n    \"A5AAFF5D-8887-42BB-8AFD-867EF557ED85\": {\n        \"name\": \"Buckingham Palace\"\n    },\n    \"F604AF56-EA77-4960-AEF7-82533CC1A8B3\": {\n        \"name\": \"River Thames near Sunset\"\n    },\n    \"7F4C26C2-67C2-4C3A-8F07-8A7BF6148C97\": {\n        \"name\": \"River Thames at Dusk\"\n    },\n    \"CE279831-1CA7-4A83-A97B-FF1E20234396\": {\n        \"name\": \"Los Angeles Int’l Airport\"\n    },\n    \"35693AEA-F8C4-4A80-B77D-C94B20A68956\": {\n        \"name\": \"Harbor Freeway\"\n    },\n    \"92E48DE9-13A1-4172-B560-29B4668A87EE\": {\n        \"name\": \"Santa Monica Beach\"\n    },\n    \"89B1643B-06DD-4DEC-B1B0-774493B0F7B7\": {\n        \"name\": \"Griffith Observatory\"\n    },\n    \"EC67726A-8212-4C5E-83CF-8412932740D2\": {\n        \"name\": \"Hollywood Hills\"\n    },\n    \"F5804DD6-5963-40DA-9FA0-39C0C6E6DEF9\": {\n        \"name\": \"Downtown\"\n    },\n    \"3BA0CFC7-E460-4B59-A817-B97F9EBB9B89\": {\n        \"name\": \"Central Park\"\n    },\n    \"b1-3\": {\n        \"name\": \"Lower Manhattan\"\n    },\n    \"840FE8E4-D952-4680-B1A7-AC5BACA2C1F8\": {\n        \"name\": \"Upper East Side\"\n    },\n    \"44166C39-8566-4ECA-BD16-43159429B52F\": {\n        \"name\": \"Seventh Avenue\"\n    },\n    \"640DFB00-FBB9-45DA-9444-9F663859F4BC\": {\n        \"name\": \"Lower Manhattan\"\n    },\n    \"b8-2\": {\n        \"name\": \"Marin Headlands\"\n    },\n    \"EE533FBD-90AE-419A-AD13-D7A60E2015D6\": {\n        \"name\": \"Marin Headlands in Fog\"\n    },\n    \"DE851E6D-C2BE-4D9F-AB54-0F9CE994DC51\": {\n        \"name\": \"Bay and Golden Gate\"\n    },\n    \"b8-3\": {\n        \"name\": \"Alamo Square\"\n    },\n    \"85CE77BF-3413-4A7B-9B0F-732E96229A73\": {\n        \"name\": \"Embarcadero, Market Street\"\n    },\n    \"b4-3\": {\n        \"name\": \"Presidio to Golden Gate\"\n    },\n    \"72B4390D-DF1D-4D51-B179-229BBAEFFF2C\": {\n        \"name\": \"Golden Gate from SF\"\n    },\n    \"b6-4\": {\n        \"name\": \"Downtown and Coit Tower\"\n    },\n    \"29BDF297-EB43-403A-8719-A78DA11A2948\": {\n        \"name\": \"Fisherman’s Wharf\"\n    },\n    \"b5-3\": {\n        \"name\": \"Embarcadero, Market Street\"\n    },\n    \"3E94AE98-EAF2-4B09-96E3-452F46BC114E\": {\n        \"name\": \"Bay Bridge\"\n    },\n    \"b2-4\": {\n        \"name\": \"Downtown and Sutro Tower\"\n    },\n    \"4AD99907-9E76-408D-A7FC-8429FF014201\": {\n        \"name\": \"Bay and Embarcadero\"\n    },\n    \"03EC0F5E-CCA8-4E0A-9FEC-5BD1CE151182\": {\n        \"name\": \"Antartica\"\n    },\n    \"737E9E24-49BE-4104-9B72-F352DE1AD2BF\": {\n        \"name\": \"North America Aurora\"\n    },\n    \"A837FA8C-C643-4705-AE92-074EFDD067F7\": {\n        \"name\": \"Africa Night\"\n    },\n    \"2F72BC1E-3D76-456C-81EB-842EBA488C27\": {\n        \"name\": \"Africa and the Middle East\"\n    },\n    \"12318CCB-3F78-43B7-A854-EFDCCE5312CD\": {\n        \"name\": \"California to Vegas\"\n    },\n    \"D5CFB2FF-5F8C-4637-816B-3E42FC1229B8\": {\n        \"name\": \"Caribbean\"\n    },\n    \"4F881F8B-A7D9-4FDB-A917-17BF6AC5A589\": {\n        \"name\": \"Caribbean Day\"\n    },\n    \"6324F6EB-E0F1-468F-AC2E-A983EBDDD53B\": {\n        \"name\": \"China\"\n    },\n    \"E5DB138A-F04E-4619-B896-DE5CB538C534\": {\n        \"name\": \"Italy to Asia\"\n    },\n    \"F439B0A7-D18C-4B14-9681-6520E6A74FE9\": {\n        \"name\": \"Iran and Afghanistan\"\n    },\n    \"7C643A39-C0B2-4BA0-8BC2-2EAA47CC580E\": {\n        \"name\": \"Ireland to Asia\"\n    },\n    \"63C042F0-90EF-4A95-B7CC-CC9A64BF8421\": {\n        \"name\": \"West Africa to the Alps\"\n    },\n    \"78911B7E-3C69-47AD-B635-9C2486F6301D\": {\n        \"name\": \"New Zealand\"\n    },\n    \"E556BBC5-D0A0-4DB1-AC77-BC76E4A526F4\": {\n        \"name\": \"Sahara and Italy\"\n    },\n    \"64D11DAB-3B57-4F14-AD2F-E59A9282FA44\": {\n        \"name\": \"Atlantic Ocean to Spain and France\"\n    },\n    \"81337355-E156-4242-AAF4-711768D30A54\": {\n        \"name\": \"Australia\"\n    },\n    \"1088217C-1410-4CF7-BDE9-8F573A4DBCD9\": {\n        \"name\": \"Caribbean to Central America\"\n    },\n    \"3C4678E4-4D3D-4A40-8817-77752AEA62EB\": {\n        \"name\": \"Nile Delta\"\n    },\n    \"87060EC2-D006-4102-98CC-3005C68BB343\": {\n        \"name\": \"South Africa to North Asia\"\n    },\n    \"F07CC61B-30FC-4614-BDAD-3240B61F6793\": {\n        \"name\": \"Palau Coral\"\n    },\n    \"6143116D-03BB-485E-864E-A8CF58ACF6F1\": {\n        \"name\": \"South African Kelp\"\n    },\n    \"2B30E324-E4FF-4CC1-BA45-A958C2D2B2EC\": {\n        \"name\": \"Barracuda\"\n    },\n    \"581A4F1A-2B6D-468C-A1BE-6F473F06D10B\": {\n        \"name\": \"Sea Stars\"\n    },\n    \"687D03A2-18A5-4181-8E85-38F3A13409B9\": {\n        \"name\": \"Bumpheads\"\n    },\n    \"537A4DAB-83B0-4B66-BCD1-05E5DBB4A268\": {\n        \"name\": \"Jacks\"\n    },\n    \"27A37B0F-738D-4644-A7A4-E33E7A6C1175\": {\n        \"name\": \"California Dolphins\"\n    },\n    \"EB3F48E7-D30F-4079-858F-1A61331D5026\": {\n        \"name\": \"California Kelp Forest\"\n    },\n    \"CE9B5D5B-B6E7-47C5-8C04-59BF182E98FB\": {\n        \"name\": \"Costa Rica Dolphins\"\n    },\n    \"58C75C62-3290-47B8-849C-56A583173570\": {\n        \"name\": \"Cownose Rays\"\n    },\n    \"3716DD4B-01C0-4F5B-8DD6-DB771EC472FB\": {\n        \"name\": \"Gray Reef Sharks\"\n    },\n    \"DD47D8E1-CB66-4C12-BFEA-2ADB0D8D1E2E\": {\n        \"name\": \"Humpback Whale\"\n    },\n    \"82175C1F-153C-4EC8-AE37-2860EA828004\": {\n        \"name\": \"Red Sea Coral\"\n    },\n    \"391BDF6E-3279-4CE1-9CA5-0F82811452D7\": {\n        \"name\": \"Seals\"\n    },\n    \"BA4ECA11-592F-4727-9221-D2A32A16EB28\": {\n        \"name\": \"Palau Jellies 1\"\n    },\n    \"E580E5A5-0888-4BE8-A4CA-F74A18A643C3\": {\n        \"name\": \"Palau Jellies 2\"\n    },\n    \"EC3DC957-D4C2-4732-AACE-7D0C0F390EC8\": {\n        \"name\": \"Palau Jellies 3\"\n    },\n    \"C7AD3D0A-7EDF-412C-A237-B3C9D27381A1\": {\n        \"name\": \"Alaskan Jellies 1\"\n    },\n    \"C6DC4E54-1130-44F8-AF6F-A551D8E8A181\": {\n        \"name\": \"Alaskan Jellies 2\"\n    },\n    \"149E7795-DBDA-4F5D-B39A-14712F841118\": {\n        \"name\": \"Tahiti Waves 1\"\n    },\n    \"8C31B06F-91A4-4F7C-93ED-56146D7F48B9\": {\n        \"name\": \"Tahiti Waves 2\"\n    },\n    \"E334A6D2-7145-47C8-9B00-C20DED08B2D5\": {\n        \"name\": \"Colorado River 1\"\n    },\n    \"DD266E1F-5DF2-4CDB-A2EB-26CE35664657\": {\n        \"name\": \"Burnt Canyon\"\n    },\n    \"F9F918CD-E15F-4F01-A326-84A44650C5C9\": {\n        \"name\": \"Sunset over Grand Canyon\"\n    },\n    \"AE0115AE-C53B-4DB9-B12F-CA4B7B630CC9\": {\n        \"name\": \"Colorado River 2\"\n    },\n    \"8002C4C8-C611-4894-A068-3D3A3C03472A\": {\n        \"name\": \"Colorado River 3\"\n    },\n    \"5C987900-AD53-469C-8210-CABBCCDDFCAE\": {\n        \"name\": \"Cuernos del Paine\"\n    },\n    \"B004358B-5A27-42E5-B49E-93FC100B2371\": {\n        \"name\": \"Lago Nordenskjöld 1\"\n    },\n    \"25A6CFB2-3570-4448-B114-244A4E454B7A\": {\n        \"name\": \"Lago Nordenskjöld 2\"\n    },\n    \"E5D58CC2-3C52-4206-9DA2-427DC88B5896\": {\n        \"name\": \"Torres del Paine\"\n    },\n    \"E5799A24-1949-4E66-A17B-B5EB05F28C5D\": {\n        \"name\": \"Half Dome\"\n    },\n    \"E487C6EF-B3FB-427B-A2BE-8CBA60F902F0\": {\n        \"name\": \"Yosemite Park 1\"\n    },\n    \"E540DEE6-4C40-42C8-9CCC-D4CB0FAD7D7B\": {\n        \"name\": \"Yosemite Park 2\"\n    },\n    \"81CA5ACD-E682-4D8B-A948-0F147EB6ED4F\": {\n        \"name\": \"Yosemite Park 3\"\n    },\n    \"4109D42A-D717-46A7-A9A2-FE53A82B25C0\": {\n        \"name\": \"Bridalveil Fall and El Capitan\"\n    },\n    \"DAD82DCE-F3AE-4AEC-8A79-1694D412FC0A\": {\n        \"name\": \"Tuolumne Meadows\"\n    },\n    \"8D04D70F-738B-441D-8D43-AF46B2BF8062\": {\n        \"name\": \"Matthes Crest\"\n    },\n    \"DDE50C77-B7CB-4488-9EB1-D1B13BF21FFE\": {\n        \"name\": \"Tungnaá\"\n    },\n    \"E54D5AFE-F362-4D48-A20D-F2C21D2B5330\": {\n        \"name\": \"Jökulgilskvísl River\"\n    },\n    \"8ACF5D77-B22C-416F-B12A-72FB35E2834F\": {\n        \"name\": \"Landmannalaugar\"\n    },\n    \"8590D0C5-E344-4FAC-A39A-FD7BC652AEDA\": {\n        \"name\": \"Langisjór\"\n    },\n    \"2F17FCCE-6CCA-4AFA-A08A-C50BF9812DA5\": {\n        \"name\": \"Mýrdalsjökull\"\n    },\n    \"F9518D54-04A7-4793-8666-CFC114D73CE5\": {\n        \"name\": \"Jökulgil\"\n    },\n    \"3954A7C4-51EC-4ABC-ABA3-6757AC91C7CF\": {\n        \"name\": \"Loch Moidart 1\"\n    },\n    \"0C747C29-4BF8-43F6-A5CC-2E012E555341\": {\n        \"name\": \"Isle of Skye\"\n    },\n    \"E161929C-0819-4BC2-8359-550C081C7D54\": {\n        \"name\": \"Loch Moidart 2\"\n    }\n}"
  },
  {
    "path": "Resources/Community/es.json",
    "content": "{\n    \"009BA758-7060-4479-8EE8-FB9B40C8FB97\": {\n        \"name\": \"Korea y Japon de noche\"\n    },\n    \"B1B5DDC5-73C8-4920-8133-BACCE38A08DE\": {\n        \"name\": \"De Ciudad de México a Nueva York\"\n    },\n    \"7719B48A-2005-4011-9280-2F64EEC6FD91\": {\n        \"name\": \"Del Norte de California a Baja\"\n    },\n    \"B876B645-3955-420E-99DF-60139E451CF3\": {\n        \"name\": \"Parque Nacional de Wulingyuan 1\"\n    },\n    \"9CCB8297-E9F5-4699-AE1F-890CFBD5E29C\": {\n        \"name\": \"Las terrazas de arroz de Longsheng\"\n    },\n    \"D5E76230-81A3-4F65-A1BA-51B8CADED625\": {\n        \"name\": \"Parque Nacional de Wulingyuan 2\"\n    },\n    \"F0236EC5-EE72-4058-A6CE-1F7D2E8253BF\": {\n        \"name\": \"La Gran Muralla 1\"\n    },\n    \"22162A9B-DB90-4517-867C-C676BC3E8E95\": {\n        \"name\": \"La Gran Muralla 2\"\n    },\n    \"044AD56C-A107-41B2-90CC-E60CCACFBCF5\": {\n        \"name\": \"La Gran Muralla 3\"\n    },\n    \"876D51F4-3D78-4221-8AD2-F9E78C0FD9B9\": {\n        \"name\": \"Carretera Sheikh Zayed\"\n    },\n    \"E991AC0C-F272-44D8-88F3-05F44EDFE3AE\": {\n        \"name\": \"Marina 1\"\n    },\n    \"00BA71CD-2C54-415A-A68A-8358E677D750\": {\n        \"name\": \"Downtown\"\n    },\n    \"3FFA2A97-7D28-49EA-AA39-5BC9051B2745\": {\n        \"name\": \"Marina 2\"\n    },\n    \"9680B8EB-CE2A-4395-AF41-402801F4D6A6\": {\n        \"name\": \"Acercándose a Burj Khalifa\"\n    },\n    \"2F11E857-4F77-4476-8033-4A1E4610AFCC\": {\n        \"name\": \"Carretera Sheikh Zayed\"\n    },\n    \"B8F204CE-6024-49AB-85F9-7CA2F6DCD226\": {\n        \"name\": \"Península de Nuussuaq\"\n    },\n    \"2F52E34C-39D4-4AB1-9025-8F7141FAA720\": {\n        \"name\": \"Fiordo de Ilulissat\"\n    },\n    \"EE01F02D-1413-436C-AB05-410F224A5B7B\": {\n        \"name\": \"Fiordo de Ilulissat\"\n    },\n    \"499995FA-E51A-4ACE-8DFD-BDF8AFF6C943\": {\n        \"name\": \"Valle Waimanu\"\n    },\n    \"12E0343D-2CD9-48EA-AB57-4D680FB6D0C7\": {\n        \"name\": \"Laupāhoehoe Nui\"\n    },\n    \"b2-2\": {\n        \"name\": \"Valle Honopū\"\n    },\n    \"258A6797-CC13-4C3A-AB35-4F25CA3BF474\": {\n        \"name\": \"Pu‘u O ‘Umi\"\n    },\n    \"3D729CFC-9000-48D3-A052-C5BD5B7A6842\": {\n        \"name\": \"La costa de Kohala\"\n    },\n    \"82BD33C9-B6D2-47E7-9C42-AA3B7758921A\": {\n        \"name\": \"Pu‘u O ‘Umi\"\n    },\n    \"FE8E1F9D-59BA-4207-B626-28E34D810D0A\": {\n        \"name\": \"Puerto Victoria 1\"\n    },\n    \"C8559883-6F3E-4AF2-8960-903710CD47B7\": {\n        \"name\": \"Cumbre Victoria\"\n    },\n    \"024891DE-B7F6-4187-BFE0-E6D237702EF0\": {\n        \"name\": \"Wan Chai\"\n    },\n    \"64EA30BD-C4B5-4CDD-86D7-DFE47E9CB9AA\": {\n        \"name\": \"Puerto Victoria 2\"\n    },\n    \"E99FA658-A59A-4A2D-9F3B-58E7BDC71A9A\": {\n        \"name\": \"Puerto Victoria\"\n    },\n    \"001C94AE-2BA4-4E77-A202-F7DE60E8B1C8\": {\n        \"name\": \"El oasis de Liwa 1\"\n    },\n    \"AFA22C08-A486-4CE8-9A13-E355B6C38559\": {\n        \"name\": \"El oasis de Liwa 2\"\n    },\n    \"58754319-8709-4AB0-8674-B34F04E7FFE2\": {\n        \"name\": \"Río Támesis\"\n    },\n    \"A5AAFF5D-8887-42BB-8AFD-867EF557ED85\": {\n        \"name\": \"Palacio de Buckingham\"\n    },\n    \"F604AF56-EA77-4960-AEF7-82533CC1A8B3\": {\n        \"name\": \"El río Támesis al atardecer\"\n    },\n    \"7F4C26C2-67C2-4C3A-8F07-8A7BF6148C97\": {\n        \"name\": \"El río Támesis al anochecer\"\n    },\n    \"CE279831-1CA7-4A83-A97B-FF1E20234396\": {\n        \"name\": \"Aeropuerto Internacional de Los Angeles\"\n    },\n    \"35693AEA-F8C4-4A80-B77D-C94B20A68956\": {\n        \"name\": \"Harbor Freeway\"\n    },\n    \"92E48DE9-13A1-4172-B560-29B4668A87EE\": {\n        \"name\": \"Playa de Santa Monica\"\n    },\n    \"89B1643B-06DD-4DEC-B1B0-774493B0F7B7\": {\n        \"name\": \"Observatorio Griffith\"\n    },\n    \"EC67726A-8212-4C5E-83CF-8412932740D2\": {\n        \"name\": \"Hollywood Hills\"\n    },\n    \"F5804DD6-5963-40DA-9FA0-39C0C6E6DEF9\": {\n        \"name\": \"El Downtown de Los Ángeles\"\n    },\n    \"3BA0CFC7-E460-4B59-A817-B97F9EBB9B89\": {\n        \"name\": \"Central Park\"\n    },\n    \"b1-3\": {\n        \"name\": \"Bajo Manhattan\"\n    },\n    \"840FE8E4-D952-4680-B1A7-AC5BACA2C1F8\": {\n        \"name\": \"Upper East Side\"\n    },\n    \"44166C39-8566-4ECA-BD16-43159429B52F\": {\n        \"name\": \"Séptima Avenida\"\n    },\n    \"640DFB00-FBB9-45DA-9444-9F663859F4BC\": {\n        \"name\": \"Bajo Manhattan\"\n    },\n    \"b8-2\": {\n        \"name\": \"Marin Headlands\"\n    },\n    \"EE533FBD-90AE-419A-AD13-D7A60E2015D6\": {\n        \"name\": \"Marin Headlands en la niebla\"\n    },\n    \"DE851E6D-C2BE-4D9F-AB54-0F9CE994DC51\": {\n        \"name\": \"Bahía de San Francisco y el Golden Gate\"\n    },\n    \"b8-3\": {\n        \"name\": \"Alamo Square\"\n    },\n    \"85CE77BF-3413-4A7B-9B0F-732E96229A73\": {\n        \"name\": \"Embarcadero, Market Street\"\n    },\n    \"b4-3\": {\n        \"name\": \"De Presidio al Golden Gate\"\n    },\n    \"72B4390D-DF1D-4D51-B179-229BBAEFFF2C\": {\n        \"name\": \"El Golden Gate desde San Francisco\"\n    },\n    \"b6-4\": {\n        \"name\": \"Downtown y la Torre Coit\"\n    },\n    \"29BDF297-EB43-403A-8719-A78DA11A2948\": {\n        \"name\": \"Fisherman’s Wharf\"\n    },\n    \"b5-3\": {\n        \"name\": \"Embarcadero, Market Street\"\n    },\n    \"3E94AE98-EAF2-4B09-96E3-452F46BC114E\": {\n        \"name\": \"Puente de la Bahía\"\n    },\n    \"b2-4\": {\n        \"name\": \"Downtown y la Torre Sutro\"\n    },\n    \"4AD99907-9E76-408D-A7FC-8429FF014201\": {\n        \"name\": \"Bahía de San Francisco y Embarcadero\"\n    },\n    \"03EC0F5E-CCA8-4E0A-9FEC-5BD1CE151182\": {\n        \"name\": \"Antártida\"\n    },\n    \"737E9E24-49BE-4104-9B72-F352DE1AD2BF\": {\n        \"name\": \"Aurora Boreal Norteamericana\"\n    },\n    \"A837FA8C-C643-4705-AE92-074EFDD067F7\": {\n        \"name\": \"Noche Africana\"\n    },\n    \"2F72BC1E-3D76-456C-81EB-842EBA488C27\": {\n        \"name\": \"Africa y Oriente Medio\"\n    },\n    \"12318CCB-3F78-43B7-A854-EFDCCE5312CD\": {\n        \"name\": \"De California a Las Vegas\"\n    },\n    \"D5CFB2FF-5F8C-4637-816B-3E42FC1229B8\": {\n        \"name\": \"El Caribe\"\n    },\n    \"4F881F8B-A7D9-4FDB-A917-17BF6AC5A589\": {\n        \"name\": \"El Caribe de dia\"\n    },\n    \"7825C73A-658F-48EE-B14C-EC56673094AC\": {\n        \"name\": \"China\"\n    },\n    \"E5DB138A-F04E-4619-B896-DE5CB538C534\": {\n        \"name\": \"De Italia a Asia\"\n    },\n    \"F439B0A7-D18C-4B14-9681-6520E6A74FE9\": {\n        \"name\": \"Irán y Afganistán\"\n    },\n    \"7C643A39-C0B2-4BA0-8BC2-2EAA47CC580E\": {\n        \"name\": \"De Irlanda a Asia\"\n    },\n    \"63C042F0-90EF-4A95-B7CC-CC9A64BF8421\": {\n        \"name\": \"De África Occidental a los Alpes\"\n    },\n    \"78911B7E-3C69-47AD-B635-9C2486F6301D\": {\n        \"name\": \"Nueva Zelanda\"\n    },\n    \"E556BBC5-D0A0-4DB1-AC77-BC76E4A526F4\": {\n        \"name\": \"El Sahara e Italia\"\n    },\n    \"64D11DAB-3B57-4F14-AD2F-E59A9282FA44\": {\n        \"name\": \"Del Océano Atlántico a España y Francia\"\n    },\n    \"81337355-E156-4242-AAF4-711768D30A54\": {\n        \"name\": \"Australia\"\n    },\n    \"1088217C-1410-4CF7-BDE9-8F573A4DBCD9\": {\n        \"name\": \"Del Caribe a América Central\"\n    },\n    \"3C4678E4-4D3D-4A40-8817-77752AEA62EB\": {\n        \"name\": \"Delta del Nilo\"\n    },\n    \"87060EC2-D006-4102-98CC-3005C68BB343\": {\n        \"name\": \"De Sudáfrica al Norte de Asia\"\n    },\n    \"F07CC61B-30FC-4614-BDAD-3240B61F6793\": {\n        \"name\": \"Corales en Palau\"\n    },\n    \"6143116D-03BB-485E-864E-A8CF58ACF6F1\": {\n        \"name\": \"Algas en Sudáfrica\"\n    },\n    \"2B30E324-E4FF-4CC1-BA45-A958C2D2B2EC\": {\n        \"name\": \"Barracuda\"\n    },\n    \"581A4F1A-2B6D-468C-A1BE-6F473F06D10B\": {\n        \"name\": \"Estrellas de mar\"\n    },\n    \"687D03A2-18A5-4181-8E85-38F3A13409B9\": {\n        \"name\": \"Pez Loro Búfalo\"\n    },\n    \"537A4DAB-83B0-4B66-BCD1-05E5DBB4A268\": {\n        \"name\": \"Jureles\"\n    },\n    \"27A37B0F-738D-4644-A7A4-E33E7A6C1175\": {\n        \"name\": \"Delfines de California\"\n    },\n    \"EB3F48E7-D30F-4079-858F-1A61331D5026\": {\n        \"name\": \"Bosque de Algas de California\"\n    },\n    \"CE9B5D5B-B6E7-47C5-8C04-59BF182E98FB\": {\n        \"name\": \"Delfines de Costa Rica\"\n    },\n    \"58C75C62-3290-47B8-849C-56A583173570\": {\n        \"name\": \"Mantarrayas\"\n    },\n    \"3716DD4B-01C0-4F5B-8DD6-DB771EC472FB\": {\n        \"name\": \"Tiburones Grises de Arrecife\"\n    },\n    \"DD47D8E1-CB66-4C12-BFEA-2ADB0D8D1E2E\": {\n        \"name\": \"Ballena Jorobada\"\n    },\n    \"82175C1F-153C-4EC8-AE37-2860EA828004\": {\n        \"name\": \"Coral del Mar Rojo\"\n    },\n    \"391BDF6E-3279-4CE1-9CA5-0F82811452D7\": {\n        \"name\": \"Focas\"\n    },\n    \"BA4ECA11-592F-4727-9221-D2A32A16EB28\": {\n        \"name\": \"Medusas en Palau 1\"\n    },\n    \"E580E5A5-0888-4BE8-A4CA-F74A18A643C3\": {\n        \"name\": \"Medusas en Palau 2\"\n    },\n    \"EC3DC957-D4C2-4732-AACE-7D0C0F390EC8\": {\n        \"name\": \"Medusas en Palau 3\"\n    },\n    \"C7AD3D0A-7EDF-412C-A237-B3C9D27381A1\": {\n        \"name\": \"Medusas en Alaska 1\"\n    },\n    \"C6DC4E54-1130-44F8-AF6F-A551D8E8A181\": {\n        \"name\": \"Medusas en Alaska 2\"\n    },\n    \"149E7795-DBDA-4F5D-B39A-14712F841118\": {\n        \"name\": \"Olas de Tahití 1\"\n    },\n    \"8C31B06F-91A4-4F7C-93ED-56146D7F48B9\": {\n        \"name\": \"Olas de Tahití 2\"\n    }\n}"
  },
  {
    "path": "Resources/Community/fr.json",
    "content": "{\n    \"009BA758-7060-4479-8EE8-FB9B40C8FB97\": {\n        \"name\": \"Corée et Japon\"\n    },\n    \"B1B5DDC5-73C8-4920-8133-BACCE38A08DE\": {\n        \"name\": \"Mexico City vers New York\"\n    },\n    \"7719B48A-2005-4011-9280-2F64EEC6FD91\": {\n        \"name\": \"Californie vers Baja\"\n    },\n    \"B876B645-3955-420E-99DF-60139E451CF3\": {\n        \"name\": \"Parc National Wulingyuan 1\"\n    },\n    \"9CCB8297-E9F5-4699-AE1F-890CFBD5E29C\": {\n        \"name\": \"Rizières en terrasses de Longji\"\n    },\n    \"D5E76230-81A3-4F65-A1BA-51B8CADED625\": {\n        \"name\": \"Parc National Wulingyuan 2\"\n    },\n    \"F0236EC5-EE72-4058-A6CE-1F7D2E8253BF\": {\n        \"name\": \"Grande Muraille 1\"\n    },\n    \"22162A9B-DB90-4517-867C-C676BC3E8E95\": {\n        \"name\": \"Grande Muraille 2\"\n    },\n    \"044AD56C-A107-41B2-90CC-E60CCACFBCF5\": {\n        \"name\": \"Grande Muraille 3\"\n    },\n    \"876D51F4-3D78-4221-8AD2-F9E78C0FD9B9\": {\n        \"name\": \"Route Sheikh Zayed\"\n    },\n    \"E991AC0C-F272-44D8-88F3-05F44EDFE3AE\": {\n        \"name\": \"Marina 1\"\n    },\n    \"00BA71CD-2C54-415A-A68A-8358E677D750\": {\n        \"name\": \"Centre ville\"\n    },\n    \"3FFA2A97-7D28-49EA-AA39-5BC9051B2745\": {\n        \"name\": \"Marina 2\"\n    },\n    \"9680B8EB-CE2A-4395-AF41-402801F4D6A6\": {\n        \"name\": \"A l'approche de la Burj Khalifa\"\n    },\n    \"2F11E857-4F77-4476-8033-4A1E4610AFCC\": {\n        \"name\": \"Route Sheikh Zayed\"\n    },\n    \"B8F204CE-6024-49AB-85F9-7CA2F6DCD226\": {\n        \"name\": \"Péninsule Nuussuaq\"\n    },\n    \"2F52E34C-39D4-4AB1-9025-8F7141FAA720\": {\n        \"name\": \"Fjord glacé d'Ilulissat\"\n    },\n    \"EE01F02D-1413-436C-AB05-410F224A5B7B\": {\n        \"name\": \"Fjord glacé d'Ilulissat\"\n    },\n    \"499995FA-E51A-4ACE-8DFD-BDF8AFF6C943\": {\n        \"name\": \"Vallée Waimanu\"\n    },\n    \"12E0343D-2CD9-48EA-AB57-4D680FB6D0C7\": {\n        \"name\": \"Laupāhoehoe Nui\"\n    },\n    \"b2-2\": {\n        \"name\": \"Vallée Honopū\"\n    },\n    \"258A6797-CC13-4C3A-AB35-4F25CA3BF474\": {\n        \"name\": \"Pu‘u O ‘Umi\"\n    },\n    \"3D729CFC-9000-48D3-A052-C5BD5B7A6842\": {\n        \"name\": \"Côte Kohala\"\n    },\n    \"82BD33C9-B6D2-47E7-9C42-AA3B7758921A\": {\n        \"name\": \"Pu‘u O ‘Umi\"\n    },\n    \"FE8E1F9D-59BA-4207-B626-28E34D810D0A\": {\n        \"name\": \"Port Victoria 1\"\n    },\n    \"C8559883-6F3E-4AF2-8960-903710CD47B7\": {\n        \"name\": \"Pic Victoria\"\n    },\n    \"024891DE-B7F6-4187-BFE0-E6D237702EF0\": {\n        \"name\": \"Wan Chai\"\n    },\n    \"64EA30BD-C4B5-4CDD-86D7-DFE47E9CB9AA\": {\n        \"name\": \"Port Victoria 2\"\n    },\n    \"E99FA658-A59A-4A2D-9F3B-58E7BDC71A9A\": {\n        \"name\": \"Port Victoria\"\n    },\n    \"001C94AE-2BA4-4E77-A202-F7DE60E8B1C8\": {\n        \"name\": \"Oasis de Liwa 1\"\n    },\n    \"AFA22C08-A486-4CE8-9A13-E355B6C38559\": {\n        \"name\": \"Oasis de Liwa 2\"\n    },\n    \"58754319-8709-4AB0-8674-B34F04E7FFE2\": {\n        \"name\": \"Tamise\"\n    },\n    \"A5AAFF5D-8887-42BB-8AFD-867EF557ED85\": {\n        \"name\": \"Palais de Buckingham\"\n    },\n    \"F604AF56-EA77-4960-AEF7-82533CC1A8B3\": {\n        \"name\": \"Tamise au coucher du soleil\"\n    },\n    \"7F4C26C2-67C2-4C3A-8F07-8A7BF6148C97\": {\n        \"name\": \"Tamise au crépuscule\"\n    },\n    \"CE279831-1CA7-4A83-A97B-FF1E20234396\": {\n        \"name\": \"Aéroport de Los Angeles\"\n    },\n    \"35693AEA-F8C4-4A80-B77D-C94B20A68956\": {\n        \"name\": \"Harbor Freeway (I-110)\"\n    },\n    \"92E48DE9-13A1-4172-B560-29B4668A87EE\": {\n        \"name\": \"Plage Santa Monica\"\n    },\n    \"89B1643B-06DD-4DEC-B1B0-774493B0F7B7\": {\n        \"name\": \"Observatoire Griffith\"\n    },\n    \"EC67726A-8212-4C5E-83CF-8412932740D2\": {\n        \"name\": \"Collines d'Hollywood\"\n    },\n    \"F5804DD6-5963-40DA-9FA0-39C0C6E6DEF9\": {\n        \"name\": \"Centre ville\"\n    },\n    \"3BA0CFC7-E460-4B59-A817-B97F9EBB9B89\": {\n        \"name\": \"Central Park\"\n    },\n    \"b1-3\": {\n        \"name\": \"Sud de Manhattan\"\n    },\n    \"840FE8E4-D952-4680-B1A7-AC5BACA2C1F8\": {\n        \"name\": \"Upper East Side\"\n    },\n    \"44166C39-8566-4ECA-BD16-43159429B52F\": {\n        \"name\": \"Septième Avenue\"\n    },\n    \"640DFB00-FBB9-45DA-9444-9F663859F4BC\": {\n        \"name\": \"Sud de Manhattan\"\n    },\n    \"b8-2\": {\n        \"name\": \"Marin Headlands\"\n    },\n    \"EE533FBD-90AE-419A-AD13-D7A60E2015D6\": {\n        \"name\": \"Marin Headlands dans le brouillard\"\n    },\n    \"DE851E6D-C2BE-4D9F-AB54-0F9CE994DC51\": {\n        \"name\": \"Bay et Golden Gate\"\n    },\n    \"b8-3\": {\n        \"name\": \"Parc d'Alamo Square\"\n    },\n    \"85CE77BF-3413-4A7B-9B0F-732E96229A73\": {\n        \"name\": \"Embarcadero, Market Street\"\n    },\n    \"b4-3\": {\n        \"name\": \"Presidio vers Golden Gate\"\n    },\n    \"72B4390D-DF1D-4D51-B179-229BBAEFFF2C\": {\n        \"name\": \"Golden Gate depuis SF\"\n    },\n    \"b6-4\": {\n        \"name\": \"Centre ville et Tour Coit\"\n    },\n    \"29BDF297-EB43-403A-8719-A78DA11A2948\": {\n        \"name\": \"Fisherman's Wharf\"\n    },\n    \"b5-3\": {\n        \"name\": \"Embarcadero, Market Street\"\n    },\n    \"3E94AE98-EAF2-4B09-96E3-452F46BC114E\": {\n        \"name\": \"Bay Bridge\"\n    },\n    \"b2-4\": {\n        \"name\": \"Centre-ville et tour Sutro\"\n    },\n    \"4AD99907-9E76-408D-A7FC-8429FF014201\": {\n        \"name\": \"Bay et Embarcadero\"\n    },\n    \"03EC0F5E-CCA8-4E0A-9FEC-5BD1CE151182\": {\n        \"name\": \"Antarctique\"\n    },\n    \"737E9E24-49BE-4104-9B72-F352DE1AD2BF\": {\n        \"name\": \"Aurore en Amérique du Nord\"\n    },\n    \"A837FA8C-C643-4705-AE92-074EFDD067F7\": {\n        \"name\": \"Nuit Africaine\"\n    },\n    \"2F72BC1E-3D76-456C-81EB-842EBA488C27\": {\n        \"name\": \"Afrique et Moyen-Orient\"\n    },\n    \"12318CCB-3F78-43B7-A854-EFDCCE5312CD\": {\n        \"name\": \"Californie vers Vegas\"\n    },\n    \"D5CFB2FF-5F8C-4637-816B-3E42FC1229B8\": {\n        \"name\": \"Caraïbes\"\n    },\n    \"4F881F8B-A7D9-4FDB-A917-17BF6AC5A589\": {\n        \"name\": \"Caraïbes de jour\"\n    },\n    \"6324F6EB-E0F1-468F-AC2E-A983EBDDD53B\": {\n        \"name\": \"Chine\"\n    },\n    \"E5DB138A-F04E-4619-B896-DE5CB538C534\": {\n        \"name\": \"Italie vers l’Asie\"\n    },\n    \"F439B0A7-D18C-4B14-9681-6520E6A74FE9\": {\n        \"name\": \"Iran et Afghanistan\"\n    },\n    \"7C643A39-C0B2-4BA0-8BC2-2EAA47CC580E\": {\n        \"name\": \"Irlande vers l’Asie\"\n    },\n    \"63C042F0-90EF-4A95-B7CC-CC9A64BF8421\": {\n        \"name\": \"Afrique de l'Ouest vers les Alpes\"\n    },\n    \"78911B7E-3C69-47AD-B635-9C2486F6301D\": {\n        \"name\": \"Nouvelle-Zélande\"\n    },\n    \"E556BBC5-D0A0-4DB1-AC77-BC76E4A526F4\": {\n        \"name\": \"Sahara et Italie\"\n    },\n    \"64D11DAB-3B57-4F14-AD2F-E59A9282FA44\": {\n        \"name\": \"Océan Atlantique vers l'Espagne et la France\"\n    },\n    \"81337355-E156-4242-AAF4-711768D30A54\": {\n        \"name\": \"Australie\"\n    },\n    \"1088217C-1410-4CF7-BDE9-8F573A4DBCD9\": {\n        \"name\": \"Caraïbes et Amérique Centrale\"\n    },\n    \"3C4678E4-4D3D-4A40-8817-77752AEA62EB\": {\n        \"name\": \"Delta du Nil\"\n    },\n    \"87060EC2-D006-4102-98CC-3005C68BB343\": {\n        \"name\": \"Afrique du Sud vers Asie du Nord\"\n    },\n    \"F07CC61B-30FC-4614-BDAD-3240B61F6793\": {\n        \"name\": \"Corail de Palaos\"\n    },\n    \"6143116D-03BB-485E-864E-A8CF58ACF6F1\": {\n        \"name\": \"Macroalgues en Afrique du Sud\"\n    },\n    \"2B30E324-E4FF-4CC1-BA45-A958C2D2B2EC\": {\n        \"name\": \"Barracuda\"\n    },\n    \"581A4F1A-2B6D-468C-A1BE-6F473F06D10B\": {\n        \"name\": \"Étoiles de mer\"\n    },\n    \"687D03A2-18A5-4181-8E85-38F3A13409B9\": {\n        \"name\": \"Poissons-perroquets à bosse\"\n    },\n    \"537A4DAB-83B0-4B66-BCD1-05E5DBB4A268\": {\n        \"name\": \"Carangues à gros yeux\"\n    },\n    \"27A37B0F-738D-4644-A7A4-E33E7A6C1175\": {\n        \"name\": \"Dauphins en Californie\"\n    },\n    \"EB3F48E7-D30F-4079-858F-1A61331D5026\": {\n        \"name\": \"Forêt de macroalgues en Californie\"\n    },\n    \"CE9B5D5B-B6E7-47C5-8C04-59BF182E98FB\": {\n        \"name\": \"Dauphins au Costa Rica\"\n    },\n    \"58C75C62-3290-47B8-849C-56A583173570\": {\n        \"name\": \"Mourines du Pacifique\"\n    },\n    \"3716DD4B-01C0-4F5B-8DD6-DB771EC472FB\": {\n        \"name\": \"Requins gris de récif\"\n    },\n    \"DD47D8E1-CB66-4C12-BFEA-2ADB0D8D1E2E\": {\n        \"name\": \"Baleine à bosse\"\n    },\n    \"82175C1F-153C-4EC8-AE37-2860EA828004\": {\n        \"name\": \"Corail de la mer Rouge\"\n    },\n    \"391BDF6E-3279-4CE1-9CA5-0F82811452D7\": {\n        \"name\": \"Otaries à fourrure\"\n    },\n    \"BA4ECA11-592F-4727-9221-D2A32A16EB28\": {\n        \"name\": \"Méduses dorées de Palaos 1\"\n    },\n    \"E580E5A5-0888-4BE8-A4CA-F74A18A643C3\": {\n        \"name\": \"Méduses dorées de Palaos 2\"\n    },\n    \"EC3DC957-D4C2-4732-AACE-7D0C0F390EC8\": {\n        \"name\": \"Méduses dorées de Palaos 3\"\n    },\n    \"C7AD3D0A-7EDF-412C-A237-B3C9D27381A1\": {\n        \"name\": \"Méduses lune de l'Alaska 1\"\n    },\n    \"C6DC4E54-1130-44F8-AF6F-A551D8E8A181\": {\n        \"name\": \"Méduses lune de l'Alaska 2\"\n    },\n    \"149E7795-DBDA-4F5D-B39A-14712F841118\": {\n        \"name\": \"Vagues à Tahiti 1\"\n    },\n    \"8C31B06F-91A4-4F7C-93ED-56146D7F48B9\": {\n        \"name\": \"Vagues à Tahiti 2\"\n    },\n    \"E334A6D2-7145-47C8-9B00-C20DED08B2D5\": {\n        \"name\": \"Fleuve Colorado 1\"\n    },\n    \"DD266E1F-5DF2-4CDB-A2EB-26CE35664657\": {\n        \"name\": \"Canyon brûlé\"\n    },\n    \"F9F918CD-E15F-4F01-A326-84A44650C5C9\": {\n        \"name\": \"Coucher de soleil sur le Grand Canyon\"\n    },\n    \"AE0115AE-C53B-4DB9-B12F-CA4B7B630CC9\": {\n        \"name\": \"Fleuve Colorado 2\"\n    },\n    \"8002C4C8-C611-4894-A068-3D3A3C03472A\": {\n        \"name\": \"Fleuve Colorado 3\"\n    },\n    \"5C987900-AD53-469C-8210-CABBCCDDFCAE\": {\n        \"name\": \"Cuernos del Paine\"\n    },\n    \"B004358B-5A27-42E5-B49E-93FC100B2371\": {\n        \"name\": \"Lac Nordenskjöld 1\"\n    },\n    \"25A6CFB2-3570-4448-B114-244A4E454B7A\": {\n        \"name\": \"Lac Nordenskjöld 2\"\n    },\n    \"E5D58CC2-3C52-4206-9DA2-427DC88B5896\": {\n        \"name\": \"Torres del Paine\"\n    },\n    \"E5799A24-1949-4E66-A17B-B5EB05F28C5D\": {\n        \"name\": \"Demi-Dome\"\n    },\n    \"E487C6EF-B3FB-427B-A2BE-8CBA60F902F0\": {\n        \"name\": \"Parc Yosemite 1\"\n    },\n    \"E540DEE6-4C40-42C8-9CCC-D4CB0FAD7D7B\": {\n        \"name\": \"Parc Yosemite 2\"\n    },\n    \"81CA5ACD-E682-4D8B-A948-0F147EB6ED4F\": {\n        \"name\": \"Parc Yosemite 3\"\n    },\n    \"4109D42A-D717-46A7-A9A2-FE53A82B25C0\": {\n        \"name\": \"Chute Bridalveil et El Capitan\"\n    },\n    \"DAD82DCE-F3AE-4AEC-8A79-1694D412FC0A\": {\n        \"name\": \"Prairies de Tuolumne\"\n    },\n    \"8D04D70F-738B-441D-8D43-AF46B2BF8062\": {\n        \"name\": \"Matthes Crest\"\n    },\n    \"DDE50C77-B7CB-4488-9EB1-D1B13BF21FFE\": {\n        \"name\": \"Tungnaá\"\n    },\n    \"E54D5AFE-F362-4D48-A20D-F2C21D2B5330\": {\n        \"name\": \"Rivière Jökulgilskvísl\"\n    },\n    \"8ACF5D77-B22C-416F-B12A-72FB35E2834F\": {\n        \"name\": \"Landmannalaugar\"\n    },\n    \"8590D0C5-E344-4FAC-A39A-FD7BC652AEDA\": {\n        \"name\": \"Langisjór\"\n    },\n    \"2F17FCCE-6CCA-4AFA-A08A-C50BF9812DA5\": {\n        \"name\": \"Mýrdalsjökull\"\n    },\n    \"F9518D54-04A7-4793-8666-CFC114D73CE5\": {\n        \"name\": \"Jökulgil\"\n    },\n    \"3954A7C4-51EC-4ABC-ABA3-6757AC91C7CF\": {\n        \"name\": \"Loch Moidart 1\"\n    },\n    \"0C747C29-4BF8-43F6-A5CC-2E012E555341\": {\n        \"name\": \"Île de Skye\"\n    },\n    \"E161929C-0819-4BC2-8359-550C081C7D54\": {\n        \"name\": \"Loch Moidart 2\"\n    }\n}"
  },
  {
    "path": "Resources/Community/he.json",
    "content": "{\n    \"009BA758-7060-4479-8EE8-FB9B40C8FB97\": {\n        \"name\": \"קוריאה ולילה ביפן\"\n    },\n    \"B1B5DDC5-73C8-4920-8133-BACCE38A08DE\": {\n        \"name\": \"מקסיקו סיטי לניו יורק\"\n    },\n    \"7719B48A-2005-4011-9280-2F64EEC6FD91\": {\n        \"name\": \"צפון קליפורניה לבאחה\"\n    },\n    \"B876B645-3955-420E-99DF-60139E451CF3\": {\n        \"name\": \"הפארק הלאומי וולינגיואן 1\"\n    },\n    \"9CCB8297-E9F5-4699-AE1F-890CFBD5E29C\": {\n        \"name\": \"טרסות אורז לונגיי\"\n    },\n    \"D5E76230-81A3-4F65-A1BA-51B8CADED625\": {\n        \"name\": \"הפארק הלאומי וולינגיואן 2\"\n    },\n    \"F0236EC5-EE72-4058-A6CE-1F7D2E8253BF\": {\n        \"name\": \"החומה הגדולה 1\"\n    },\n    \"22162A9B-DB90-4517-867C-C676BC3E8E95\": {\n        \"name\": \"החומה הגדולה 2\"\n    },\n    \"044AD56C-A107-41B2-90CC-E60CCACFBCF5\": {\n        \"name\": \"החומה הגדולה 3\"\n    },\n    \"876D51F4-3D78-4221-8AD2-F9E78C0FD9B9\": {\n        \"name\": \"רחוב שייח זאיד\"\n    },\n    \"E991AC0C-F272-44D8-88F3-05F44EDFE3AE\": {\n        \"name\": \"מרינה 1\"\n    },\n    \"00BA71CD-2C54-415A-A68A-8358E677D750\": {\n        \"name\": \"מרכז העיר\"\n    },\n    \"3FFA2A97-7D28-49EA-AA39-5BC9051B2745\": {\n        \"name\": \"מרינה 2\"\n    },\n    \"9680B8EB-CE2A-4395-AF41-402801F4D6A6\": {\n        \"name\": \"מתקרב לבורז' ח'ליפה\"\n    },\n    \"2F11E857-4F77-4476-8033-4A1E4610AFCC\": {\n        \"name\": \"רחוב שייח זאיד\"\n    },\n    \"B8F204CE-6024-49AB-85F9-7CA2F6DCD226\": {\n        \"name\": \"חצי האי ניוסואק\"\n    },\n    \"2F52E34C-39D4-4AB1-9025-8F7141FAA720\": {\n        \"name\": \"אייספיורד אילוליסאט\"\n    },\n    \"EE01F02D-1413-436C-AB05-410F224A5B7B\": {\n        \"name\": \"אייספיורד אילוליסאט\"\n    },\n    \"499995FA-E51A-4ACE-8DFD-BDF8AFF6C943\": {\n        \"name\": \"עמק ויאמאנו\"\n    },\n    \"12E0343D-2CD9-48EA-AB57-4D680FB6D0C7\": {\n        \"name\": \"לאופאהוהו ניווי\"\n    },\n    \"b2-2\": {\n        \"name\": \"עמק הונפו\"\n    },\n    \"258A6797-CC13-4C3A-AB35-4F25CA3BF474\": {\n        \"name\": \"פו או אומי\"\n    },\n    \"3D729CFC-9000-48D3-A052-C5BD5B7A6842\": {\n        \"name\": \"קו החוף קוהלה\"\n    },\n    \"82BD33C9-B6D2-47E7-9C42-AA3B7758921A\": {\n        \"name\": \"פו או אומי\"\n    },\n    \"FE8E1F9D-59BA-4207-B626-28E34D810D0A\": {\n        \"name\": \"נמל ויקטוריה 1\"\n    },\n    \"C8559883-6F3E-4AF2-8960-903710CD47B7\": {\n        \"name\": \"פסגת ויקטוריה\"\n    },\n    \"024891DE-B7F6-4187-BFE0-E6D237702EF0\": {\n        \"name\": \"וואן צ'אי\"\n    },\n    \"64EA30BD-C4B5-4CDD-86D7-DFE47E9CB9AA\": {\n        \"name\": \"נמל ויקטוריה 2\"\n    },\n    \"E99FA658-A59A-4A2D-9F3B-58E7BDC71A9A\": {\n        \"name\": \"נמל ויקטוריה\"\n    },\n    \"001C94AE-2BA4-4E77-A202-F7DE60E8B1C8\": {\n        \"name\": \"נווה מדבר ליווה 1\"\n    },\n    \"AFA22C08-A486-4CE8-9A13-E355B6C38559\": {\n        \"name\": \"נווה מדבר ליווה 2\"\n    },\n    \"58754319-8709-4AB0-8674-B34F04E7FFE2\": {\n        \"name\": \"נהר התמזה\"\n    },\n    \"A5AAFF5D-8887-42BB-8AFD-867EF557ED85\": {\n        \"name\": \"ארמון בקינגהאם\"\n    },\n    \"F604AF56-EA77-4960-AEF7-82533CC1A8B3\": {\n        \"name\": \"נהר התמזה קרוב לשקיעה\"\n    },\n    \"7F4C26C2-67C2-4C3A-8F07-8A7BF6148C97\": {\n        \"name\": \"נהר התמזה בשעת בין ערביים\"\n    },\n    \"CE279831-1CA7-4A83-A97B-FF1E20234396\": {\n        \"name\": \"נמל התעופה הבינלאומי של לוס אנג'לס\"\n    },\n    \"35693AEA-F8C4-4A80-B77D-C94B20A68956\": {\n        \"name\": \"הכביש המהיר הארבור\"\n    },\n    \"92E48DE9-13A1-4172-B560-29B4668A87EE\": {\n        \"name\": \"חוף סנטה מוניקה\"\n    },\n    \"89B1643B-06DD-4DEC-B1B0-774493B0F7B7\": {\n        \"name\": \"מצפה גריפית\"\n    },\n    \"EC67726A-8212-4C5E-83CF-8412932740D2\": {\n        \"name\": \"הוליווד הילס\"\n    },\n    \"F5804DD6-5963-40DA-9FA0-39C0C6E6DEF9\": {\n        \"name\": \"מרכז העיר\"\n    },\n    \"3BA0CFC7-E460-4B59-A817-B97F9EBB9B89\": {\n        \"name\": \"סנטרל פארק\"\n    },\n    \"b1-3\": {\n        \"name\": \"מנהטן התחתונה\"\n    },\n    \"840FE8E4-D952-4680-B1A7-AC5BACA2C1F8\": {\n        \"name\": \"אפר איסט סייד\"\n    },\n    \"44166C39-8566-4ECA-BD16-43159429B52F\": {\n        \"name\": \"השדרה השביעית\"\n    },\n    \"640DFB00-FBB9-45DA-9444-9F663859F4BC\": {\n        \"name\": \"מנהטן התחתונה\"\n    },\n    \"b8-2\": {\n        \"name\": \"צוקי מארין\"\n    },\n    \"EE533FBD-90AE-419A-AD13-D7A60E2015D6\": {\n        \"name\": \"צוקי מארין בערפל\"\n    },\n    \"DE851E6D-C2BE-4D9F-AB54-0F9CE994DC51\": {\n        \"name\": \"המפרץ וגשר גולדן גייט\"\n    },\n    \"b8-3\": {\n        \"name\": \"כיכר אלאמו\"\n    },\n    \"85CE77BF-3413-4A7B-9B0F-732E96229A73\": {\n        \"name\": \"רחוב השוק, אמברקדרו\"\n    },\n    \"b4-3\": {\n        \"name\": \"פרסידיו לכיוון גשר גולדן גייט\"\n    },\n    \"72B4390D-DF1D-4D51-B179-229BBAEFFF2C\": {\n        \"name\": \"גשר הגולדן גייט מכיוון סן פרנסיסקו\"\n    },\n    \"b6-4\": {\n        \"name\": \"מרכז העיר וקוויט טאוור\"\n    },\n    \"29BDF297-EB43-403A-8719-A78DA11A2948\": {\n        \"name\": \"רציף הדייג\"\n    },\n    \"b5-3\": {\n        \"name\": \"רחוב השוק, אמברקדרו\"\n    },\n    \"3E94AE98-EAF2-4B09-96E3-452F46BC114E\": {\n        \"name\": \"גשר המפרץ\"\n    },\n    \"b2-4\": {\n        \"name\": \"מרכז העיר ומגדל סוטרו\"\n    },\n    \"4AD99907-9E76-408D-A7FC-8429FF014201\": {\n        \"name\": \"ביי ואמברקדרו\"\n    },\n    \"03EC0F5E-CCA8-4E0A-9FEC-5BD1CE151182\": {\n        \"name\": \"אנטארטיקה\"\n    },\n    \"737E9E24-49BE-4104-9B72-F352DE1AD2BF\": {\n        \"name\": \"אורורה בצפון אמריקה\"\n    },\n    \"A837FA8C-C643-4705-AE92-074EFDD067F7\": {\n        \"name\": \"לילה אפריקני\"\n    },\n    \"2F72BC1E-3D76-456C-81EB-842EBA488C27\": {\n        \"name\": \"אפריקה והמזרח התיכון\"\n    },\n    \"12318CCB-3F78-43B7-A854-EFDCCE5312CD\": {\n        \"name\": \"קליפורניה לווגאס\"\n    },\n    \"D5CFB2FF-5F8C-4637-816B-3E42FC1229B8\": {\n        \"name\": \"הקאריביים\"\n    },\n    \"4F881F8B-A7D9-4FDB-A917-17BF6AC5A589\": {\n        \"name\": \"יום קריבי\"\n    },\n    \"7825C73A-658F-48EE-B14C-EC56673094AC\": {\n        \"name\": \"סין\"\n    },\n    \"E5DB138A-F04E-4619-B896-DE5CB538C534\": {\n        \"name\": \"איטליה לאסיה\"\n    },\n    \"F439B0A7-D18C-4B14-9681-6520E6A74FE9\": {\n        \"name\": \"אירן ואפגניסטן\"\n    },\n    \"7C643A39-C0B2-4BA0-8BC2-2EAA47CC580E\": {\n        \"name\": \"אירלנד לאסיה\"\n    },\n    \"63C042F0-90EF-4A95-B7CC-CC9A64BF8421\": {\n        \"name\": \"מערב אפריקה ועד לאלפים\"\n    },\n    \"78911B7E-3C69-47AD-B635-9C2486F6301D\": {\n        \"name\": \"ניו זילנד\"\n    },\n    \"E556BBC5-D0A0-4DB1-AC77-BC76E4A526F4\": {\n        \"name\": \"סהרה ואיטליה\"\n    },\n    \"64D11DAB-3B57-4F14-AD2F-E59A9282FA44\": {\n        \"name\": \"Atlantic Ocean to Spain and France\"\n    },\n    \"81337355-E156-4242-AAF4-711768D30A54\": {\n        \"name\": \"Australia\"\n    },\n    \"1088217C-1410-4CF7-BDE9-8F573A4DBCD9\": {\n        \"name\": \"Caribbean to Central America\"\n    },\n    \"3C4678E4-4D3D-4A40-8817-77752AEA62EB\": {\n        \"name\": \"Nile Delta\"\n    },\n    \"87060EC2-D006-4102-98CC-3005C68BB343\": {\n        \"name\": \"South Africa to North Asia\"\n    },\n    \"F07CC61B-30FC-4614-BDAD-3240B61F6793\": {\n        \"name\": \"Palau Coral\"\n    },\n    \"6143116D-03BB-485E-864E-A8CF58ACF6F1\": {\n        \"name\": \"South African Kelp\"\n    },\n    \"2B30E324-E4FF-4CC1-BA45-A958C2D2B2EC\": {\n        \"name\": \"Barracuda\"\n    },\n    \"581A4F1A-2B6D-468C-A1BE-6F473F06D10B\": {\n        \"name\": \"Sea Stars\"\n    },\n    \"687D03A2-18A5-4181-8E85-38F3A13409B9\": {\n        \"name\": \"Bumpheads\"\n    },\n    \"537A4DAB-83B0-4B66-BCD1-05E5DBB4A268\": {\n        \"name\": \"Jacks\"\n    },\n    \"27A37B0F-738D-4644-A7A4-E33E7A6C1175\": {\n        \"name\": \"California Dolphins\"\n    },\n    \"EB3F48E7-D30F-4079-858F-1A61331D5026\": {\n        \"name\": \"California Kelp Forest\"\n    },\n    \"CE9B5D5B-B6E7-47C5-8C04-59BF182E98FB\": {\n        \"name\": \"Costa Rica Dolphins\"\n    },\n    \"58C75C62-3290-47B8-849C-56A583173570\": {\n        \"name\": \"Cownose Rays\"\n    },\n    \"3716DD4B-01C0-4F5B-8DD6-DB771EC472FB\": {\n        \"name\": \"Gray Reef Sharks\"\n    },\n    \"DD47D8E1-CB66-4C12-BFEA-2ADB0D8D1E2E\": {\n        \"name\": \"Humpback Whale\"\n    },\n    \"82175C1F-153C-4EC8-AE37-2860EA828004\": {\n        \"name\": \"Red Sea Coral\"\n    },\n    \"391BDF6E-3279-4CE1-9CA5-0F82811452D7\": {\n        \"name\": \"Seals\"\n    },\n    \"BA4ECA11-592F-4727-9221-D2A32A16EB28\": {\n        \"name\": \"Palau Jellies 1\"\n    },\n    \"E580E5A5-0888-4BE8-A4CA-F74A18A643C3\": {\n        \"name\": \"Palau Jellies 2\"\n    },\n    \"EC3DC957-D4C2-4732-AACE-7D0C0F390EC8\": {\n        \"name\": \"Palau Jellies 3\"\n    },\n    \"C7AD3D0A-7EDF-412C-A237-B3C9D27381A1\": {\n        \"name\": \"Alaskan Jellies 1\"\n    },\n    \"C6DC4E54-1130-44F8-AF6F-A551D8E8A181\": {\n        \"name\": \"Alaskan Jellies 2\"\n    },\n    \"149E7795-DBDA-4F5D-B39A-14712F841118\": {\n        \"name\": \"Tahiti Waves 1\"\n    },\n    \"8C31B06F-91A4-4F7C-93ED-56146D7F48B9\": {\n        \"name\": \"Tahiti Waves 2\"\n    }\n}"
  },
  {
    "path": "Resources/Community/hu.json",
    "content": "{\n    \"009BA758-7060-4479-8EE8-FB9B40C8FB97\": {\n        \"name\": \"Korea és Japán éjszaka\"\n    },\n    \"B1B5DDC5-73C8-4920-8133-BACCE38A08DE\": {\n        \"name\": \"Mexikóváros és New York között\"\n    },\n    \"7719B48A-2005-4011-9280-2F64EEC6FD91\": {\n        \"name\": \"Észak-Kalifornia és Baja között\"\n    },\n    \"B876B645-3955-420E-99DF-60139E451CF3\": {\n        \"name\": \"Wulingyuan Nemzeti Park 1\"\n    },\n    \"9CCB8297-E9F5-4699-AE1F-890CFBD5E29C\": {\n        \"name\": \"Longji rizsteraszok\"\n    },\n    \"D5E76230-81A3-4F65-A1BA-51B8CADED625\": {\n        \"name\": \"Wulingyuan Nemzeti Park 2\"\n    },\n    \"F0236EC5-EE72-4058-A6CE-1F7D2E8253BF\": {\n        \"name\": \"Nagy Fal 1\"\n    },\n    \"22162A9B-DB90-4517-867C-C676BC3E8E95\": {\n        \"name\": \"Nagy Fal 2\"\n    },\n    \"044AD56C-A107-41B2-90CC-E60CCACFBCF5\": {\n        \"name\": \"Nagy fal 3\"\n    },\n    \"876D51F4-3D78-4221-8AD2-F9E78C0FD9B9\": {\n        \"name\": \"Sheikh Zayed út\"\n    },\n    \"E991AC0C-F272-44D8-88F3-05F44EDFE3AE\": {\n        \"name\": \"Marina 1\"\n    },\n    \"00BA71CD-2C54-415A-A68A-8358E677D750\": {\n        \"name\": \"Belváros\"\n    },\n    \"3FFA2A97-7D28-49EA-AA39-5BC9051B2745\": {\n        \"name\": \"Marina 2\"\n    },\n    \"9680B8EB-CE2A-4395-AF41-402801F4D6A6\": {\n        \"name\": \"Közeledés a Burj Khalifa felé\"\n    },\n    \"2F11E857-4F77-4476-8033-4A1E4610AFCC\": {\n        \"name\": \"Sheikh Zayed út\"\n    },\n    \"B8F204CE-6024-49AB-85F9-7CA2F6DCD226\": {\n        \"name\": \"Nuussuaq-félsziget\"\n    },\n    \"2F52E34C-39D4-4AB1-9025-8F7141FAA720\": {\n        \"name\": \"Ilulissat jégfjord\"\n    },\n    \"EE01F02D-1413-436C-AB05-410F224A5B7B\": {\n        \"name\": \"Ilulissat jégfjord\"\n    },\n    \"499995FA-E51A-4ACE-8DFD-BDF8AFF6C943\": {\n        \"name\": \"Waimanu-völgy\"\n    },\n    \"12E0343D-2CD9-48EA-AB57-4D680FB6D0C7\": {\n        \"name\": \"Laupāhoehoe Nui\"\n    },\n    \"b2-2\": {\n        \"name\": \"Honopū-völgy\"\n    },\n    \"258A6797-CC13-4C3A-AB35-4F25CA3BF474\": {\n        \"name\": \"Pu'u O 'Umi\"\n    },\n    \"3D729CFC-9000-48D3-A052-C5BD5B7A6842\": {\n        \"name\": \"Kohala partvonala\"\n    },\n    \"82BD33C9-B6D2-47E7-9C42-AA3B7758921A\": {\n        \"name\": \"Pu'u O 'Umi\"\n    },\n    \"FE8E1F9D-59BA-4207-B626-28E34D810D0A\": {\n        \"name\": \"Viktória kikötő 1\"\n    },\n    \"C8559883-6F3E-4AF2-8960-903710CD47B7\": {\n        \"name\": \"Viktória csúcs\"\n    },\n    \"024891DE-B7F6-4187-BFE0-E6D237702EF0\": {\n        \"name\": \"Wan Chai\"\n    },\n    \"64EA30BD-C4B5-4CDD-86D7-DFE47E9CB9AA\": {\n        \"name\": \"Victoria kikötő 2\"\n    },\n    \"E99FA658-A59A-4A2D-9F3B-58E7BDC71A9A\": {\n        \"name\": \"Victoria kikötő\"\n    },\n    \"001C94AE-2BA4-4E77-A202-F7DE60E8B1C8\": {\n        \"name\": \"Liwa oázis 1\"\n    },\n    \"AFA22C08-A486-4CE8-9A13-E355B6C38559\": {\n        \"name\": \"Liwa oázis 2\"\n    },\n    \"58754319-8709-4AB0-8674-B34F04E7FFE2\": {\n        \"name\": \"Temze\"\n    },\n    \"A5AAFF5D-8887-42BB-8AFD-867EF557ED85\": {\n        \"name\": \"Buckingham-palota\"\n    },\n    \"F604AF56-EA77-4960-AEF7-82533CC1A8B3\": {\n        \"name\": \"Temze naplementéhez közel\"\n    },\n    \"7F4C26C2-67C2-4C3A-8F07-8A7BF6148C97\": {\n        \"name\": \"Temze alkonyatkor\"\n    },\n    \"CE279831-1CA7-4A83-A97B-FF1E20234396\": {\n        \"name\": \"Los Angeles-i nemzetközi repülőtér\"\n    },\n    \"35693AEA-F8C4-4A80-B77D-C94B20A68956\": {\n        \"name\": \"Kikötői autópálya\"\n    },\n    \"92E48DE9-13A1-4172-B560-29B4668A87EE\": {\n        \"name\": \"Santa Monica Beach\"\n    },\n    \"89B1643B-06DD-4DEC-B1B0-774493B0F7B7\": {\n        \"name\": \"Griffith Obszervatórium\"\n    },\n    \"EC67726A-8212-4C5E-83CF-8412932740D2\": {\n        \"name\": \"Hollywoodi hegyek\"\n    },\n    \"F5804DD6-5963-40DA-9FA0-39C0C6E6DEF9\": {\n        \"name\": \"Belváros\"\n    },\n    \"3BA0CFC7-E460-4B59-A817-B97F9EBB9B89\": {\n        \"name\": \"Central Park\"\n    },\n    \"b1-3\": {\n        \"name\": \"Alsó Manhattan\"\n    },\n    \"840FE8E4-D952-4680-B1A7-AC5BACA2C1F8\": {\n        \"name\": \"Upper East Side\"\n    },\n    \"44166C39-8566-4ECA-BD16-43159429B52F\": {\n        \"name\": \"Hetedik sugárút\"\n    },\n    \"640DFB00-FBB9-45DA-9444-9F663859F4BC\": {\n        \"name\": \"Alsó Manhattan\"\n    },\n    \"b8-2\": {\n        \"name\": \"Marin Headlands\"\n    },\n    \"EE533FBD-90AE-419A-AD13-D7A60E2015D6\": {\n        \"name\": \"Marin Headlands a ködben\"\n    },\n    \"DE851E6D-C2BE-4D9F-AB54-0F9CE994DC51\": {\n        \"name\": \"Golden Gate és az öböl\"\n    },\n    \"b8-3\": {\n        \"name\": \"Alamo Square\"\n    },\n    \"85CE77BF-3413-4A7B-9B0F-732E96229A73\": {\n        \"name\": \"Embarcadero, Market Street\"\n    },\n    \"b4-3\": {\n        \"name\": \"Presidio és Golden Gate között\"\n    },\n    \"72B4390D-DF1D-4D51-B179-229BBAEFFF2C\": {\n        \"name\": \"Golden Gate SF felől\"\n    },\n    \"b6-4\": {\n        \"name\": \"Belváros és a Coit torony\"\n    },\n    \"29BDF297-EB43-403A-8719-A78DA11A2948\": {\n        \"name\": \"Fisherman's Wharf\"\n    },\n    \"b5-3\": {\n        \"name\": \"Embarcadero, Market Street\"\n    },\n    \"3E94AE98-EAF2-4B09-96E3-452F46BC114E\": {\n        \"name\": \"Öböl híd\"\n    },\n    \"b2-4\": {\n        \"name\": \"Belváros és a Sutro torony\"\n    },\n    \"4AD99907-9E76-408D-A7FC-8429FF014201\": {\n        \"name\": \"Bay és Embarcadero \"\n    },\n    \"03EC0F5E-CCA8-4E0A-9FEC-5BD1CE151182\": {\n        \"name\": \"Antarktisz\"\n    },\n    \"737E9E24-49BE-4104-9B72-F352DE1AD2BF\": {\n        \"name\": \"Észak-amerikai sarki fény\"\n    },\n    \"A837FA8C-C643-4705-AE92-074EFDD067F7\": {\n        \"name\": \"Afrika éjszaka\"\n    },\n    \"2F72BC1E-3D76-456C-81EB-842EBA488C27\": {\n        \"name\": \"Afrika és a Közel-Kelet\"\n    },\n    \"12318CCB-3F78-43B7-A854-EFDCCE5312CD\": {\n        \"name\": \"Kalifornia és Vegas között\"\n    },\n    \"D5CFB2FF-5F8C-4637-816B-3E42FC1229B8\": {\n        \"name\": \"Karib-szigetek\"\n    },\n    \"4F881F8B-A7D9-4FDB-A917-17BF6AC5A589\": {\n        \"name\": \"Karibi nap\"\n    },\n    \"6324F6EB-E0F1-468F-AC2E-A983EBDDD53B\": {\n        \"name\": \"Kína\"\n    },\n    \"E5DB138A-F04E-4619-B896-DE5CB538C534\": {\n        \"name\": \"Olaszország és Ázsia között\"\n    },\n    \"F439B0A7-D18C-4B14-9681-6520E6A74FE9\": {\n        \"name\": \"Irán és Afganisztán\"\n    },\n    \"7C643A39-C0B2-4BA0-8BC2-2EAA47CC580E\": {\n        \"name\": \"Írország és Ázsia között\"\n    },\n    \"63C042F0-90EF-4A95-B7CC-CC9A64BF8421\": {\n        \"name\": \"Nyugat-Afrikától az Alpokig\"\n    },\n    \"78911B7E-3C69-47AD-B635-9C2486F6301D\": {\n        \"name\": \"Új-Zéland\"\n    },\n    \"E556BBC5-D0A0-4DB1-AC77-BC76E4A526F4\": {\n        \"name\": \"Szahara és Olaszország\"\n    },\n    \"64D11DAB-3B57-4F14-AD2F-E59A9282FA44\": {\n        \"name\": \"Az Atlanti-óceánon át Spanyol- és Franciaország felett\"\n    },\n    \"81337355-E156-4242-AAF4-711768D30A54\": {\n        \"name\": \"Ausztrália\"\n    },\n    \"1088217C-1410-4CF7-BDE9-8F573A4DBCD9\": {\n        \"name\": \"Karib-térség és Közép-Amerika között\"\n    },\n    \"3C4678E4-4D3D-4A40-8817-77752AEA62EB\": {\n        \"name\": \"Nílus-delta\"\n    },\n    \"87060EC2-D006-4102-98CC-3005C68BB343\": {\n        \"name\": \"Dél-Afrika és Észak-Ázsia között\"\n    },\n    \"F07CC61B-30FC-4614-BDAD-3240B61F6793\": {\n        \"name\": \"Palau korall\"\n    },\n    \"6143116D-03BB-485E-864E-A8CF58ACF6F1\": {\n        \"name\": \"Dél-afrikai tengeri moszat\"\n    },\n    \"2B30E324-E4FF-4CC1-BA45-A958C2D2B2EC\": {\n        \"name\": \"Barracudák\"\n    },\n    \"581A4F1A-2B6D-468C-A1BE-6F473F06D10B\": {\n        \"name\": \"Tengeri csillagok\"\n    },\n    \"687D03A2-18A5-4181-8E85-38F3A13409B9\": {\n        \"name\": \"Bütykösfejű papagájhalak\"\n    },\n    \"537A4DAB-83B0-4B66-BCD1-05E5DBB4A268\": {\n        \"name\": \"Tüskés makrélák\"\n    },\n    \"27A37B0F-738D-4644-A7A4-E33E7A6C1175\": {\n        \"name\": \"Kaliforniai delfinek\"\n    },\n    \"EB3F48E7-D30F-4079-858F-1A61331D5026\": {\n        \"name\": \"Kaliforniai moszaterdő\"\n    },\n    \"CE9B5D5B-B6E7-47C5-8C04-59BF182E98FB\": {\n        \"name\": \"Costa Rica-i delfinek\"\n    },\n    \"58C75C62-3290-47B8-849C-56A583173570\": {\n        \"name\": \"Tehénorrú ráják\"\n    },\n    \"3716DD4B-01C0-4F5B-8DD6-DB771EC472FB\": {\n        \"name\": \"Szürke szirtcápa\"\n    },\n    \"DD47D8E1-CB66-4C12-BFEA-2ADB0D8D1E2E\": {\n        \"name\": \"Hosszúszárnyú bálna\"\n    },\n    \"82175C1F-153C-4EC8-AE37-2860EA828004\": {\n        \"name\": \"Vörös-tengeri korall\"\n    },\n    \"391BDF6E-3279-4CE1-9CA5-0F82811452D7\": {\n        \"name\": \"Fókák\"\n    },\n    \"BA4ECA11-592F-4727-9221-D2A32A16EB28\": {\n        \"name\": \"Palau medúzák 1\"\n    },\n    \"E580E5A5-0888-4BE8-A4CA-F74A18A643C3\": {\n        \"name\": \"Palau medúzák 2\"\n    },\n    \"EC3DC957-D4C2-4732-AACE-7D0C0F390EC8\": {\n        \"name\": \"Palau medúzák 3\"\n    },\n    \"C7AD3D0A-7EDF-412C-A237-B3C9D27381A1\": {\n        \"name\": \"Alaszkai medúzák 1\"\n    },\n    \"C6DC4E54-1130-44F8-AF6F-A551D8E8A181\": {\n        \"name\": \"Alaszkai medúzák 2\"\n    },\n    \"149E7795-DBDA-4F5D-B39A-14712F841118\": {\n        \"name\": \"Tahiti hullámok 1\"\n    },\n    \"8C31B06F-91A4-4F7C-93ED-56146D7F48B9\": {\n        \"name\": \"Tahiti hullámok 2\"\n    },\n    \"E334A6D2-7145-47C8-9B00-C20DED08B2D5\": {\n        \"name\": \"Colorado folyó 1\"\n    },\n    \"DD266E1F-5DF2-4CDB-A2EB-26CE35664657\": {\n        \"name\": \"Burnt Canyon\"\n    },\n    \"F9F918CD-E15F-4F01-A326-84A44650C5C9\": {\n        \"name\": \"Naplemente a Grand Canyon felett\"\n    },\n    \"AE0115AE-C53B-4DB9-B12F-CA4B7B630CC9\": {\n        \"name\": \"Colorado folyó 2\"\n    },\n    \"8002C4C8-C611-4894-A068-3D3A3C03472A\": {\n        \"name\": \"Colorado folyó 3\"\n    },\n    \"5C987900-AD53-469C-8210-CABBCCDDFCAE\": {\n        \"name\": \"Cuernos del Paine\"\n    },\n    \"B004358B-5A27-42E5-B49E-93FC100B2371\": {\n        \"name\": \"Lago Nordenskjöld 1\"\n    },\n    \"25A6CFB2-3570-4448-B114-244A4E454B7A\": {\n        \"name\": \"Lago Nordenskjöld 2\"\n    },\n    \"E5D58CC2-3C52-4206-9DA2-427DC88B5896\": {\n        \"name\": \"Torres del Paine\"\n    },\n    \"E5799A24-1949-4E66-A17B-B5EB05F28C5D\": {\n        \"name\": \"Half Dome\"\n    },\n    \"E487C6EF-B3FB-427B-A2BE-8CBA60F902F0\": {\n        \"name\": \"Yosemite Park 1\"\n    },\n    \"E540DEE6-4C40-42C8-9CCC-D4CB0FAD7D7B\": {\n        \"name\": \"Yosemite Park 2\"\n    },\n    \"81CA5ACD-E682-4D8B-A948-0F147EB6ED4F\": {\n        \"name\": \"Yosemite Park 3\"\n    },\n    \"4109D42A-D717-46A7-A9A2-FE53A82B25C0\": {\n        \"name\": \"Bridalveil vízesés és El Capitan\"\n    },\n    \"DAD82DCE-F3AE-4AEC-8A79-1694D412FC0A\": {\n        \"name\": \"Tuolumne Meadows\"\n    },\n    \"8D04D70F-738B-441D-8D43-AF46B2BF8062\": {\n        \"name\": \"Matthes Crest\"\n    },\n    \"DDE50C77-B7CB-4488-9EB1-D1B13BF21FFE\": {\n        \"name\": \"Tungnaá\"\n    },\n    \"E54D5AFE-F362-4D48-A20D-F2C21D2B5330\": {\n        \"name\": \"Jökulgilskvísl folyó\"\n    },\n    \"8ACF5D77-B22C-416F-B12A-72FB35E2834F\": {\n        \"name\": \"Landmannalaugar\"\n    },\n    \"8590D0C5-E344-4FAC-A39A-FD7BC652AEDA\": {\n        \"name\": \"Langisjór\"\n    },\n    \"2F17FCCE-6CCA-4AFA-A08A-C50BF9812DA5\": {\n        \"name\": \"Mýrdalsjökull\"\n    },\n    \"F9518D54-04A7-4793-8666-CFC114D73CE5\": {\n        \"name\": \"Jökulgil\"\n    },\n    \"3954A7C4-51EC-4ABC-ABA3-6757AC91C7CF\": {\n        \"name\": \"Loch Moidart 1\"\n    },\n    \"0C747C29-4BF8-43F6-A5CC-2E012E555341\": {\n        \"name\": \"Skye szigete\"\n    },\n    \"E161929C-0819-4BC2-8359-550C081C7D54\": {\n        \"name\": \"Loch Moidart 2\"\n    }\n}"
  },
  {
    "path": "Resources/Community/it.json",
    "content": "{\n    \"009BA758-7060-4479-8EE8-FB9B40C8FB97\": {\n        \"name\": \"Corea e Giappone di notte\"\n    },\n    \"B1B5DDC5-73C8-4920-8133-BACCE38A08DE\": {\n        \"name\": \"Da Città del Messico a New York\"\n    },\n    \"7719B48A-2005-4011-9280-2F64EEC6FD91\": {\n        \"name\": \"Dalla California del Nord a Baja\"\n    },\n    \"B876B645-3955-420E-99DF-60139E451CF3\": {\n        \"name\": \"Parco nazionale Wulingyuan 1\"\n    },\n    \"9CCB8297-E9F5-4699-AE1F-890CFBD5E29C\": {\n        \"name\": \"Terrazze di riso Longji\"\n    },\n    \"D5E76230-81A3-4F65-A1BA-51B8CADED625\": {\n        \"name\": \"Parco nazionale Wulingyuan 2\"\n    },\n    \"F0236EC5-EE72-4058-A6CE-1F7D2E8253BF\": {\n        \"name\": \"Grande Muraglia 1\"\n    },\n    \"22162A9B-DB90-4517-867C-C676BC3E8E95\": {\n        \"name\": \"Grande Muraglia 2\"\n    },\n    \"044AD56C-A107-41B2-90CC-E60CCACFBCF5\": {\n        \"name\": \"Grande Muraglia 3\"\n    },\n    \"876D51F4-3D78-4221-8AD2-F9E78C0FD9B9\": {\n        \"name\": \"Sheikh Zayed Road\"\n    },\n    \"E991AC0C-F272-44D8-88F3-05F44EDFE3AE\": {\n        \"name\": \"Marina 1\"\n    },\n    \"00BA71CD-2C54-415A-A68A-8358E677D750\": {\n        \"name\": \"Centro città\"\n    },\n    \"3FFA2A97-7D28-49EA-AA39-5BC9051B2745\": {\n        \"name\": \"Marina 2\"\n    },\n    \"9680B8EB-CE2A-4395-AF41-402801F4D6A6\": {\n        \"name\": \"Avvicinamento al Burj Khalifa\"\n    },\n    \"2F11E857-4F77-4476-8033-4A1E4610AFCC\": {\n        \"name\": \"Strada dello Sceicco\"\n    },\n    \"B8F204CE-6024-49AB-85F9-7CA2F6DCD226\": {\n        \"name\": \"Penisola di Nuussuaq\"\n    },\n    \"2F52E34C-39D4-4AB1-9025-8F7141FAA720\": {\n        \"name\": \"Fiordo Di Ilulissat\"\n    },\n    \"EE01F02D-1413-436C-AB05-410F224A5B7B\": {\n        \"name\": \"Fiordo Di Ilulissat\"\n    },\n    \"499995FA-E51A-4ACE-8DFD-BDF8AFF6C943\": {\n        \"name\": \"Valle di Waimanu\"\n    },\n    \"12E0343D-2CD9-48EA-AB57-4D680FB6D0C7\": {\n        \"name\": \"Laupāhoehoe Nui\"\n    },\n    \"b2-2\": {\n        \"name\": \"Valle di Honopū\"\n    },\n    \"258A6797-CC13-4C3A-AB35-4F25CA3BF474\": {\n        \"name\": \"Pu'u O 'Umi\"\n    },\n    \"3D729CFC-9000-48D3-A052-C5BD5B7A6842\": {\n        \"name\": \"Costa di Kohala\"\n    },\n    \"82BD33C9-B6D2-47E7-9C42-AA3B7758921A\": {\n        \"name\": \"Pu'u O 'Umi\"\n    },\n    \"FE8E1F9D-59BA-4207-B626-28E34D810D0A\": {\n        \"name\": \"Il Porto Di Victoria, 1\"\n    },\n    \"C8559883-6F3E-4AF2-8960-903710CD47B7\": {\n        \"name\": \"Victoria Peak\"\n    },\n    \"024891DE-B7F6-4187-BFE0-E6D237702EF0\": {\n        \"name\": \"Wan Chai\"\n    },\n    \"64EA30BD-C4B5-4CDD-86D7-DFE47E9CB9AA\": {\n        \"name\": \"Il Porto Di Victoria 2\"\n    },\n    \"E99FA658-A59A-4A2D-9F3B-58E7BDC71A9A\": {\n        \"name\": \"Porto di Victoria\"\n    },\n    \"001C94AE-2BA4-4E77-A202-F7DE60E8B1C8\": {\n        \"name\": \"Oasi Di Liwa, 1\"\n    },\n    \"AFA22C08-A486-4CE8-9A13-E355B6C38559\": {\n        \"name\": \"Oasi di Liwa 2\"\n    },\n    \"58754319-8709-4AB0-8674-B34F04E7FFE2\": {\n        \"name\": \"Il Tamigi\"\n    },\n    \"A5AAFF5D-8887-42BB-8AFD-867EF557ED85\": {\n        \"name\": \"Buckingham Palace\"\n    },\n    \"F604AF56-EA77-4960-AEF7-82533CC1A8B3\": {\n        \"name\": \"Fiume Tamigi al tramonto\"\n    },\n    \"7F4C26C2-67C2-4C3A-8F07-8A7BF6148C97\": {\n        \"name\": \"Il Tamigi al crepuscolo\"\n    },\n    \"CE279831-1CA7-4A83-A97B-FF1E20234396\": {\n        \"name\": \"Aeroporto Internazionale di Los Angeles\"\n    },\n    \"35693AEA-F8C4-4A80-B77D-C94B20A68956\": {\n        \"name\": \"Harbor Freeway\"\n    },\n    \"92E48DE9-13A1-4172-B560-29B4668A87EE\": {\n        \"name\": \"Spiaggia di Santa Monica\"\n    },\n    \"89B1643B-06DD-4DEC-B1B0-774493B0F7B7\": {\n        \"name\": \"L'Osservatorio Griffith\"\n    },\n    \"EC67726A-8212-4C5E-83CF-8412932740D2\": {\n        \"name\": \"Colline Di Hollywood\"\n    },\n    \"F5804DD6-5963-40DA-9FA0-39C0C6E6DEF9\": {\n        \"name\": \"Centro città\"\n    },\n    \"3BA0CFC7-E460-4B59-A817-B97F9EBB9B89\": {\n        \"name\": \"Central Park\"\n    },\n    \"b1-3\": {\n        \"name\": \"Lower Manhattan\"\n    },\n    \"840FE8E4-D952-4680-B1A7-AC5BACA2C1F8\": {\n        \"name\": \"Upper East Side\"\n    },\n    \"44166C39-8566-4ECA-BD16-43159429B52F\": {\n        \"name\": \"Settima Avenue\"\n    },\n    \"640DFB00-FBB9-45DA-9444-9F663859F4BC\": {\n        \"name\": \"Lower Manhattan\"\n    },\n    \"b8-2\": {\n        \"name\": \"Marin Headlands\"\n    },\n    \"EE533FBD-90AE-419A-AD13-D7A60E2015D6\": {\n        \"name\": \"Marin Headlands nella nebbia\"\n    },\n    \"DE851E6D-C2BE-4D9F-AB54-0F9CE994DC51\": {\n        \"name\": \"Baia e Golden Gate\"\n    },\n    \"b8-3\": {\n        \"name\": \"Alamo Square\"\n    },\n    \"85CE77BF-3413-4A7B-9B0F-732E96229A73\": {\n        \"name\": \"Embarcadero, Market Street\"\n    },\n    \"b4-3\": {\n        \"name\": \"Dal Presidio al Golden Gate\"\n    },\n    \"72B4390D-DF1D-4D51-B179-229BBAEFFF2C\": {\n        \"name\": \"Golden Gate da San Francisco\"\n    },\n    \"b6-4\": {\n        \"name\": \"Centro città e Coit Tower\"\n    },\n    \"29BDF297-EB43-403A-8719-A78DA11A2948\": {\n        \"name\": \"Fisherman's Wharf\"\n    },\n    \"b5-3\": {\n        \"name\": \"Embarcadero, Market Street\"\n    },\n    \"3E94AE98-EAF2-4B09-96E3-452F46BC114E\": {\n        \"name\": \"Bay Bridge\"\n    },\n    \"b2-4\": {\n        \"name\": \"Centro città e Torre Sutro\"\n    },\n    \"4AD99907-9E76-408D-A7FC-8429FF014201\": {\n        \"name\": \"Baia e Embarcadero\"\n    },\n    \"03EC0F5E-CCA8-4E0A-9FEC-5BD1CE151182\": {\n        \"name\": \"Antartide\"\n    },\n    \"737E9E24-49BE-4104-9B72-F352DE1AD2BF\": {\n        \"name\": \"Aurora in Nord America\"\n    },\n    \"A837FA8C-C643-4705-AE92-074EFDD067F7\": {\n        \"name\": \"Africa di notte\"\n    },\n    \"2F72BC1E-3D76-456C-81EB-842EBA488C27\": {\n        \"name\": \"Africa e Medio Oriente\"\n    },\n    \"12318CCB-3F78-43B7-A854-EFDCCE5312CD\": {\n        \"name\": \"California verso Las Vegas\"\n    },\n    \"D5CFB2FF-5F8C-4637-816B-3E42FC1229B8\": {\n        \"name\": \"Caraibi\"\n    },\n    \"4F881F8B-A7D9-4FDB-A917-17BF6AC5A589\": {\n        \"name\": \"Caraibi di giorno\"\n    },\n    \"7825C73A-658F-48EE-B14C-EC56673094AC\": {\n        \"name\": \"Cina\"\n    },\n    \"E5DB138A-F04E-4619-B896-DE5CB538C534\": {\n        \"name\": \"Italia verso l'Asia\"\n    },\n    \"F439B0A7-D18C-4B14-9681-6520E6A74FE9\": {\n        \"name\": \"Iran e Afghanistan\"\n    },\n    \"7C643A39-C0B2-4BA0-8BC2-2EAA47CC580E\": {\n        \"name\": \"Irlanda verso l'Asia\"\n    },\n    \"63C042F0-90EF-4A95-B7CC-CC9A64BF8421\": {\n        \"name\": \"Africa occidentale verso le Alpi\"\n    },\n    \"78911B7E-3C69-47AD-B635-9C2486F6301D\": {\n        \"name\": \"Nuova Zelanda\"\n    },\n    \"E556BBC5-D0A0-4DB1-AC77-BC76E4A526F4\": {\n        \"name\": \"Sahara e Italia\"\n    },\n    \"64D11DAB-3B57-4F14-AD2F-E59A9282FA44\": {\n        \"name\": \"Oceano Atlantico verso la Spagna e Francia\"\n    },\n    \"81337355-E156-4242-AAF4-711768D30A54\": {\n        \"name\": \"Australia\"\n    },\n    \"1088217C-1410-4CF7-BDE9-8F573A4DBCD9\": {\n        \"name\": \"Caraibi verso l'America Centrale\"\n    },\n    \"3C4678E4-4D3D-4A40-8817-77752AEA62EB\": {\n        \"name\": \"Delta del Nilo\"\n    },\n    \"87060EC2-D006-4102-98CC-3005C68BB343\": {\n        \"name\": \"Sud Africa verso l'Asia del Nord\"\n    },\n    \"F07CC61B-30FC-4614-BDAD-3240B61F6793\": {\n        \"name\": \"Corallo a Palau\"\n    },\n    \"6143116D-03BB-485E-864E-A8CF58ACF6F1\": {\n        \"name\": \"Alghe Kelp in Sud Africa\"\n    },\n    \"2B30E324-E4FF-4CC1-BA45-A958C2D2B2EC\": {\n        \"name\": \"Barracuda\"\n    },\n    \"581A4F1A-2B6D-468C-A1BE-6F473F06D10B\": {\n        \"name\": \"Stelle marine\"\n    },\n    \"687D03A2-18A5-4181-8E85-38F3A13409B9\": {\n        \"name\": \"Pesce Pappagallo Gibboso\"\n    },\n    \"537A4DAB-83B0-4B66-BCD1-05E5DBB4A268\": {\n        \"name\": \"Jack (bigeye)\"\n    },\n    \"27A37B0F-738D-4644-A7A4-E33E7A6C1175\": {\n        \"name\": \"Delfini in California\"\n    },\n    \"EB3F48E7-D30F-4079-858F-1A61331D5026\": {\n        \"name\": \"Foresta di Kelp in California\"\n    },\n    \"CE9B5D5B-B6E7-47C5-8C04-59BF182E98FB\": {\n        \"name\": \"Delfini in Costa Rica\"\n    },\n    \"58C75C62-3290-47B8-849C-56A583173570\": {\n        \"name\": \"Razza cownose\"\n    },\n    \"3716DD4B-01C0-4F5B-8DD6-DB771EC472FB\": {\n        \"name\": \"Squali grigi\"\n    },\n    \"DD47D8E1-CB66-4C12-BFEA-2ADB0D8D1E2E\": {\n        \"name\": \"Megattera\"\n    },\n    \"82175C1F-153C-4EC8-AE37-2860EA828004\": {\n        \"name\": \"Corallo del Mar Rosso\"\n    },\n    \"391BDF6E-3279-4CE1-9CA5-0F82811452D7\": {\n        \"name\": \"Foche\"\n    },\n    \"BA4ECA11-592F-4727-9221-D2A32A16EB28\": {\n        \"name\": \"Meduse in Palau 1\"\n    },\n    \"E580E5A5-0888-4BE8-A4CA-F74A18A643C3\": {\n        \"name\": \"Meduse in Palau 2\"\n    },\n    \"EC3DC957-D4C2-4732-AACE-7D0C0F390EC8\": {\n        \"name\": \"Meduse in Palau 3\"\n    },\n    \"C7AD3D0A-7EDF-412C-A237-B3C9D27381A1\": {\n        \"name\": \"Meduse in Alaska 1\"\n    },\n    \"C6DC4E54-1130-44F8-AF6F-A551D8E8A181\": {\n        \"name\": \"Meduse in Alaska 2\"\n    },\n    \"149E7795-DBDA-4F5D-B39A-14712F841118\": {\n        \"name\": \"Onde a Tahiti 1\"\n    },\n    \"8C31B06F-91A4-4F7C-93ED-56146D7F48B9\": {\n        \"name\": \"Onde a Tahiti 2\"\n    }\n}"
  },
  {
    "path": "Resources/Community/ja.json",
    "content": "{\n    \"009BA758-7060-4479-8EE8-FB9B40C8FB97\": {\n        \"name\": \"韓国と日本の夜\"\n    },\n    \"B1B5DDC5-73C8-4920-8133-BACCE38A08DE\": {\n        \"name\": \"メキシコ・シティからニューヨークへ\"\n    },\n    \"7719B48A-2005-4011-9280-2F64EEC6FD91\": {\n        \"name\": \"北カリフォルニアからバハ\"\n    },\n    \"B876B645-3955-420E-99DF-60139E451CF3\": {\n        \"name\": \"武陵源国立公園 1\"\n    },\n    \"9CCB8297-E9F5-4699-AE1F-890CFBD5E29C\": {\n        \"name\": \"龍脊棚田\"\n    },\n    \"D5E76230-81A3-4F65-A1BA-51B8CADED625\": {\n        \"name\": \"武陵源国立公園 2\"\n    },\n    \"F0236EC5-EE72-4058-A6CE-1F7D2E8253BF\": {\n        \"name\": \"万里の長城 1\"\n    },\n    \"22162A9B-DB90-4517-867C-C676BC3E8E95\": {\n        \"name\": \"万里の長城 2\"\n    },\n    \"044AD56C-A107-41B2-90CC-E60CCACFBCF5\": {\n        \"name\": \"万里の長城 3\"\n    },\n    \"876D51F4-3D78-4221-8AD2-F9E78C0FD9B9\": {\n        \"name\": \"シェイク・ザイード・ロード\"\n    },\n    \"E991AC0C-F272-44D8-88F3-05F44EDFE3AE\": {\n        \"name\": \"マリーナ 1\"\n    },\n    \"00BA71CD-2C54-415A-A68A-8358E677D750\": {\n        \"name\": \"ダウンタウン\"\n    },\n    \"3FFA2A97-7D28-49EA-AA39-5BC9051B2745\": {\n        \"name\": \"マリーナ 2\"\n    },\n    \"9680B8EB-CE2A-4395-AF41-402801F4D6A6\": {\n        \"name\": \"ブルジュ・ハリファに接近\"\n    },\n    \"2F11E857-4F77-4476-8033-4A1E4610AFCC\": {\n        \"name\": \"シェイク・ザイード・ロード\"\n    },\n    \"B8F204CE-6024-49AB-85F9-7CA2F6DCD226\": {\n        \"name\": \"ヌウスアク半島\"\n    },\n    \"2F52E34C-39D4-4AB1-9025-8F7141FAA720\": {\n        \"name\": \"イルリサット・アイスフィヨルド\"\n    },\n    \"EE01F02D-1413-436C-AB05-410F224A5B7B\": {\n        \"name\": \"イルリサット・アイスフィヨルド\"\n    },\n    \"499995FA-E51A-4ACE-8DFD-BDF8AFF6C943\": {\n        \"name\": \"ワイマヌ渓谷\"\n    },\n    \"12E0343D-2CD9-48EA-AB57-4D680FB6D0C7\": {\n        \"name\": \"ラウパーホーホー・ヌイ\"\n    },\n    \"b2-2\": {\n        \"name\": \"ホノプ渓谷\"\n    },\n    \"258A6797-CC13-4C3A-AB35-4F25CA3BF474\": {\n        \"name\": \"プーウ・オウ・ウミ\"\n    },\n    \"3D729CFC-9000-48D3-A052-C5BD5B7A6842\": {\n        \"name\": \"コハラの海岸線\"\n    },\n    \"82BD33C9-B6D2-47E7-9C42-AA3B7758921A\": {\n        \"name\": \"プーウ・オウ・ウミ\"\n    },\n    \"FE8E1F9D-59BA-4207-B626-28E34D810D0A\": {\n        \"name\": \"ビクトリア・ハーバー 1\"\n    },\n    \"C8559883-6F3E-4AF2-8960-903710CD47B7\": {\n        \"name\": \"ビクトリア・ピーク\"\n    },\n    \"024891DE-B7F6-4187-BFE0-E6D237702EF0\": {\n        \"name\": \"ワンチャイ\"\n    },\n    \"64EA30BD-C4B5-4CDD-86D7-DFE47E9CB9AA\": {\n        \"name\": \"ビクトリア・ハーバー 2\"\n    },\n    \"E99FA658-A59A-4A2D-9F3B-58E7BDC71A9A\": {\n        \"name\": \"ビクトリア・ハーバー\"\n    },\n    \"001C94AE-2BA4-4E77-A202-F7DE60E8B1C8\": {\n        \"name\": \"リワ・オアシス 1\"\n    },\n    \"AFA22C08-A486-4CE8-9A13-E355B6C38559\": {\n        \"name\": \"リワ・オアシス 2\"\n    },\n    \"58754319-8709-4AB0-8674-B34F04E7FFE2\": {\n        \"name\": \"テムズ川\"\n    },\n    \"A5AAFF5D-8887-42BB-8AFD-867EF557ED85\": {\n        \"name\": \"バッキンガム宮殿\"\n    },\n    \"F604AF56-EA77-4960-AEF7-82533CC1A8B3\": {\n        \"name\": \"日没近くのテムズ川\"\n    },\n    \"7F4C26C2-67C2-4C3A-8F07-8A7BF6148C97\": {\n        \"name\": \"夕暮れ時にテムズ川\"\n    },\n    \"CE279831-1CA7-4A83-A97B-FF1E20234396\": {\n        \"name\": \"ロサンゼルス国際空港\"\n    },\n    \"35693AEA-F8C4-4A80-B77D-C94B20A68956\": {\n        \"name\": \"ハーバー・フリーウェイ\"\n    },\n    \"92E48DE9-13A1-4172-B560-29B4668A87EE\": {\n        \"name\": \"サンタモニカ・ビーチ\"\n    },\n    \"89B1643B-06DD-4DEC-B1B0-774493B0F7B7\": {\n        \"name\": \"グリフィス天文台\"\n    },\n    \"EC67726A-8212-4C5E-83CF-8412932740D2\": {\n        \"name\": \"ハリウッド・ヒルズ\"\n    },\n    \"F5804DD6-5963-40DA-9FA0-39C0C6E6DEF9\": {\n        \"name\": \"ダウンタウン\"\n    },\n    \"3BA0CFC7-E460-4B59-A817-B97F9EBB9B89\": {\n        \"name\": \"セントラル・パーク\"\n    },\n    \"b1-3\": {\n        \"name\": \"ローワー・マンハッタン\"\n    },\n    \"840FE8E4-D952-4680-B1A7-AC5BACA2C1F8\": {\n        \"name\": \"アッパー・イースト・サイド\"\n    },\n    \"44166C39-8566-4ECA-BD16-43159429B52F\": {\n        \"name\": \"7番街\"\n    },\n    \"640DFB00-FBB9-45DA-9444-9F663859F4BC\": {\n        \"name\": \"ローワー・マンハッタン\"\n    },\n    \"b8-2\": {\n        \"name\": \"マリン・ヘッドランズ\"\n    },\n    \"EE533FBD-90AE-419A-AD13-D7A60E2015D6\": {\n        \"name\": \"霧の中のマリン・ヘッドランズ\"\n    },\n    \"DE851E6D-C2BE-4D9F-AB54-0F9CE994DC51\": {\n        \"name\": \"ベイとゴールデン・ゲート\"\n    },\n    \"b8-3\": {\n        \"name\": \"アラモ広場\"\n    },\n    \"85CE77BF-3413-4A7B-9B0F-732E96229A73\": {\n        \"name\": \"エンバカデロ、マーケット・ストリート\"\n    },\n    \"b4-3\": {\n        \"name\": \"プレシディオからゴールデンゲートへ\"\n    },\n    \"72B4390D-DF1D-4D51-B179-229BBAEFFF2C\": {\n        \"name\": \"SFからのゴールデンゲート\"\n    },\n    \"b6-4\": {\n        \"name\": \"ダウンタウンとコイト・タワー\"\n    },\n    \"29BDF297-EB43-403A-8719-A78DA11A2948\": {\n        \"name\": \"フィッシャーマンズ・ワーフ\"\n    },\n    \"b5-3\": {\n        \"name\": \"エンバカデロ、マーケット・ストリート\"\n    },\n    \"3E94AE98-EAF2-4B09-96E3-452F46BC114E\": {\n        \"name\": \"ベイ・ブリッジ\"\n    },\n    \"b2-4\": {\n        \"name\": \"ダウンタウンとストロ・タワー\"\n    },\n    \"4AD99907-9E76-408D-A7FC-8429FF014201\": {\n        \"name\": \"ベイとエンバカデロ\"\n    },\n    \"03EC0F5E-CCA8-4E0A-9FEC-5BD1CE151182\": {\n        \"name\": \"南極\"\n    },\n    \"737E9E24-49BE-4104-9B72-F352DE1AD2BF\": {\n        \"name\": \"北米のオーロラ\"\n    },\n    \"A837FA8C-C643-4705-AE92-074EFDD067F7\": {\n        \"name\": \"アフリカの夜\"\n    },\n    \"2F72BC1E-3D76-456C-81EB-842EBA488C27\": {\n        \"name\": \"アフリカと中東\"\n    },\n    \"12318CCB-3F78-43B7-A854-EFDCCE5312CD\": {\n        \"name\": \"カリフォルニアからラスベガス\"\n    },\n    \"D5CFB2FF-5F8C-4637-816B-3E42FC1229B8\": {\n        \"name\": \"カリブ海\"\n    },\n    \"4F881F8B-A7D9-4FDB-A917-17BF6AC5A589\": {\n        \"name\": \"カリブ海の日\"\n    },\n    \"7825C73A-658F-48EE-B14C-EC56673094AC\": {\n        \"name\": \"中国\"\n    },\n    \"E5DB138A-F04E-4619-B896-DE5CB538C534\": {\n        \"name\": \"イタリアからアジアへ\"\n    },\n    \"F439B0A7-D18C-4B14-9681-6520E6A74FE9\": {\n        \"name\": \"イランとアフガニスタン\"\n    },\n    \"7C643A39-C0B2-4BA0-8BC2-2EAA47CC580E\": {\n        \"name\": \"アイルランドからアジアへ\"\n    },\n    \"63C042F0-90EF-4A95-B7CC-CC9A64BF8421\": {\n        \"name\": \"西アフリカからアルプスまで\"\n    },\n    \"78911B7E-3C69-47AD-B635-9C2486F6301D\": {\n        \"name\": \"ニュージーランド\"\n    },\n    \"E556BBC5-D0A0-4DB1-AC77-BC76E4A526F4\": {\n        \"name\": \"サハラとイタリア\"\n    },\n    \"64D11DAB-3B57-4F14-AD2F-E59A9282FA44\": {\n        \"name\": \"大西洋からスペインとフランスへ\"\n    },\n    \"81337355-E156-4242-AAF4-711768D30A54\": {\n        \"name\": \"オーストラリア\"\n    },\n    \"1088217C-1410-4CF7-BDE9-8F573A4DBCD9\": {\n        \"name\": \"カリブ海から中央アメリカ\"\n    },\n    \"3C4678E4-4D3D-4A40-8817-77752AEA62EB\": {\n        \"name\": \"ナイル川デルタ\"\n    },\n    \"87060EC2-D006-4102-98CC-3005C68BB343\": {\n        \"name\": \"南アフリカから北アジアへ\"\n    },\n    \"F07CC61B-30FC-4614-BDAD-3240B61F6793\": {\n        \"name\": \"パラオの珊瑚\"\n    },\n    \"6143116D-03BB-485E-864E-A8CF58ACF6F1\": {\n        \"name\": \"南アフリカの昆布\"\n    },\n    \"2B30E324-E4FF-4CC1-BA45-A958C2D2B2EC\": {\n        \"name\": \"バラクーダ\"\n    },\n    \"581A4F1A-2B6D-468C-A1BE-6F473F06D10B\": {\n        \"name\": \"ヒトデ\"\n    },\n    \"687D03A2-18A5-4181-8E85-38F3A13409B9\": {\n        \"name\": \"カンムリブダイ\"\n    },\n    \"537A4DAB-83B0-4B66-BCD1-05E5DBB4A268\": {\n        \"name\": \"ギンガメアジ\"\n    },\n    \"27A37B0F-738D-4644-A7A4-E33E7A6C1175\": {\n        \"name\": \"カリフォルニアのイルカ\"\n    },\n    \"EB3F48E7-D30F-4079-858F-1A61331D5026\": {\n        \"name\": \"カリフォルニアの昆布の森\"\n    },\n    \"CE9B5D5B-B6E7-47C5-8C04-59BF182E98FB\": {\n        \"name\": \"コスタリカのイルカ\"\n    },\n    \"58C75C62-3290-47B8-849C-56A583173570\": {\n        \"name\": \"クロガネウシバナトビエイ \"\n    },\n    \"3716DD4B-01C0-4F5B-8DD6-DB771EC472FB\": {\n        \"name\": \"オグロメジロザメ\"\n    },\n    \"DD47D8E1-CB66-4C12-BFEA-2ADB0D8D1E2E\": {\n        \"name\": \"ザトウクジラ\"\n    },\n    \"82175C1F-153C-4EC8-AE37-2860EA828004\": {\n        \"name\": \"紅海のサンゴ\"\n    },\n    \"391BDF6E-3279-4CE1-9CA5-0F82811452D7\": {\n        \"name\": \"アザラシ\"\n    },\n    \"BA4ECA11-592F-4727-9221-D2A32A16EB28\": {\n        \"name\": \"パラオのクラゲ 1\"\n    },\n    \"E580E5A5-0888-4BE8-A4CA-F74A18A643C3\": {\n        \"name\": \"パラオのクラゲ 2\"\n    },\n    \"EC3DC957-D4C2-4732-AACE-7D0C0F390EC8\": {\n        \"name\": \"パラオのクラゲ 3\"\n    },\n    \"C7AD3D0A-7EDF-412C-A237-B3C9D27381A1\": {\n        \"name\": \"アラスカのクラゲ 1\"\n    },\n    \"C6DC4E54-1130-44F8-AF6F-A551D8E8A181\": {\n        \"name\": \"アラスカのクラゲ 2\"\n    },\n    \"149E7795-DBDA-4F5D-B39A-14712F841118\": {\n        \"name\": \"タヒチの波 1\"\n    },\n    \"8C31B06F-91A4-4F7C-93ED-56146D7F48B9\": {\n        \"name\": \"タヒチの波 2\"\n    }\n}"
  },
  {
    "path": "Resources/Community/ko.json",
    "content": "{\n    \"009BA758-7060-4479-8EE8-FB9B40C8FB97\": {\n        \"name\": \"한국과 일본의 밤\"\n    },\n    \"B1B5DDC5-73C8-4920-8133-BACCE38A08DE\": {\n        \"name\": \"멕시코시티에서 뉴욕까지\"\n    },\n    \"7719B48A-2005-4011-9280-2F64EEC6FD91\": {\n        \"name\": \"미국 캘리포니아 북부에서 멕시코 바하까지\"\n    },\n    \"B876B645-3955-420E-99DF-60139E451CF3\": {\n        \"name\": \"장자지에 무릉원 1\"\n    },\n    \"9CCB8297-E9F5-4699-AE1F-890CFBD5E29C\": {\n        \"name\": \"롱성롱지지역의 계단식 논\"\n    },\n    \"D5E76230-81A3-4F65-A1BA-51B8CADED625\": {\n        \"name\": \"장자지에 무릉원 2\"\n    },\n    \"F0236EC5-EE72-4058-A6CE-1F7D2E8253BF\": {\n        \"name\": \"만리장성 1\"\n    },\n    \"22162A9B-DB90-4517-867C-C676BC3E8E95\": {\n        \"name\": \"만리장성 2\"\n    },\n    \"044AD56C-A107-41B2-90CC-E60CCACFBCF5\": {\n        \"name\": \"만리장성 3\"\n    },\n    \"876D51F4-3D78-4221-8AD2-F9E78C0FD9B9\": {\n        \"name\": \"셰이크 자이드 도로\"\n    },\n    \"E991AC0C-F272-44D8-88F3-05F44EDFE3AE\": {\n        \"name\": \"마리나 1\"\n    },\n    \"00BA71CD-2C54-415A-A68A-8358E677D750\": {\n        \"name\": \"시내\"\n    },\n    \"3FFA2A97-7D28-49EA-AA39-5BC9051B2745\": {\n        \"name\": \"마리나 2\"\n    },\n    \"9680B8EB-CE2A-4395-AF41-402801F4D6A6\": {\n        \"name\": \"부르즈 할리파\"\n    },\n    \"2F11E857-4F77-4476-8033-4A1E4610AFCC\": {\n        \"name\": \"셰이크 자이드 도로\"\n    },\n    \"B8F204CE-6024-49AB-85F9-7CA2F6DCD226\": {\n        \"name\": \"누우수아크 반도\"\n    },\n    \"2F52E34C-39D4-4AB1-9025-8F7141FAA720\": {\n        \"name\": \"일룰리사트 아이스피오르드\"\n    },\n    \"EE01F02D-1413-436C-AB05-410F224A5B7B\": {\n        \"name\": \"일룰리사트 아이스피오르드\"\n    },\n    \"499995FA-E51A-4ACE-8DFD-BDF8AFF6C943\": {\n        \"name\": \"와이마누 밸리\"\n    },\n    \"12E0343D-2CD9-48EA-AB57-4D680FB6D0C7\": {\n        \"name\": \"라우바호회 누이\"\n    },\n    \"b2-2\": {\n        \"name\": \"호노푸 밸리\"\n    },\n    \"258A6797-CC13-4C3A-AB35-4F25CA3BF474\": {\n        \"name\": \"푸우 오 '우미\"\n    },\n    \"3D729CFC-9000-48D3-A052-C5BD5B7A6842\": {\n        \"name\": \"카할라 해안\"\n    },\n    \"82BD33C9-B6D2-47E7-9C42-AA3B7758921A\": {\n        \"name\": \"푸우 오 '우미\"\n    },\n    \"FE8E1F9D-59BA-4207-B626-28E34D810D0A\": {\n        \"name\": \"빅토리아 항구 1\"\n    },\n    \"C8559883-6F3E-4AF2-8960-903710CD47B7\": {\n        \"name\": \"빅토리아 피크\"\n    },\n    \"024891DE-B7F6-4187-BFE0-E6D237702EF0\": {\n        \"name\": \"완차이\"\n    },\n    \"64EA30BD-C4B5-4CDD-86D7-DFE47E9CB9AA\": {\n        \"name\": \"빅토리아 항구 2\"\n    },\n    \"E99FA658-A59A-4A2D-9F3B-58E7BDC71A9A\": {\n        \"name\": \"빅토리아 항구\"\n    },\n    \"001C94AE-2BA4-4E77-A202-F7DE60E8B1C8\": {\n        \"name\": \"리와 오아시스 1\"\n    },\n    \"AFA22C08-A486-4CE8-9A13-E355B6C38559\": {\n        \"name\": \"리와 오아시스 2\"\n    },\n    \"58754319-8709-4AB0-8674-B34F04E7FFE2\": {\n        \"name\": \"템스강\"\n    },\n    \"A5AAFF5D-8887-42BB-8AFD-867EF557ED85\": {\n        \"name\": \"버킹엄 궁전\"\n    },\n    \"F604AF56-EA77-4960-AEF7-82533CC1A8B3\": {\n        \"name\": \"템스강의 일몰\"\n    },\n    \"7F4C26C2-67C2-4C3A-8F07-8A7BF6148C97\": {\n        \"name\": \"황혼의 템스강\"\n    },\n    \"CE279831-1CA7-4A83-A97B-FF1E20234396\": {\n        \"name\": \"로스앤젤레스 국제공항\"\n    },\n    \"35693AEA-F8C4-4A80-B77D-C94B20A68956\": {\n        \"name\": \"하버 프리웨이\"\n    },\n    \"92E48DE9-13A1-4172-B560-29B4668A87EE\": {\n        \"name\": \"산타모니카 해변\"\n    },\n    \"89B1643B-06DD-4DEC-B1B0-774493B0F7B7\": {\n        \"name\": \"그리피스 천문대\"\n    },\n    \"EC67726A-8212-4C5E-83CF-8412932740D2\": {\n        \"name\": \"할리우드 힐스\"\n    },\n    \"F5804DD6-5963-40DA-9FA0-39C0C6E6DEF9\": {\n        \"name\": \"시내\"\n    },\n    \"3BA0CFC7-E460-4B59-A817-B97F9EBB9B89\": {\n        \"name\": \"센트럴 파크\"\n    },\n    \"b1-3\": {\n        \"name\": \"맨해튼 남부\"\n    },\n    \"840FE8E4-D952-4680-B1A7-AC5BACA2C1F8\": {\n        \"name\": \"어퍼 이스트 사이드\"\n    },\n    \"44166C39-8566-4ECA-BD16-43159429B52F\": {\n        \"name\": \"7번가\"\n    },\n    \"640DFB00-FBB9-45DA-9444-9F663859F4BC\": {\n        \"name\": \"맨해튼 남부\"\n    },\n    \"b8-2\": {\n        \"name\": \"마린 헤드랜드\"\n    },\n    \"EE533FBD-90AE-419A-AD13-D7A60E2015D6\": {\n        \"name\": \"안개 속의 마린 헤드랜드\"\n    },\n    \"DE851E6D-C2BE-4D9F-AB54-0F9CE994DC51\": {\n        \"name\": \"샌프란시스코만과 금문교\"\n    },\n    \"b8-3\": {\n        \"name\": \"알라모 스퀘어\"\n    },\n    \"85CE77BF-3413-4A7B-9B0F-732E96229A73\": {\n        \"name\": \"엠바카데로와 마켓 스트리트\"\n    },\n    \"b4-3\": {\n        \"name\": \"미국 샌프란시스코 프레시디오에서 금문교까지\"\n    },\n    \"72B4390D-DF1D-4D51-B179-229BBAEFFF2C\": {\n        \"name\": \"금문교에서 바라본 샌프란시스코\"\n    },\n    \"b6-4\": {\n        \"name\": \"샌프란시스코 시내와 코잇타워\"\n    },\n    \"29BDF297-EB43-403A-8719-A78DA11A2948\": {\n        \"name\": \"샌프란시스코 피셔맨스 워프\"\n    },\n    \"b5-3\": {\n        \"name\": \"엠바카데로와 마켓 스트리트\"\n    },\n    \"3E94AE98-EAF2-4B09-96E3-452F46BC114E\": {\n        \"name\": \"샌프란시스코-오클랜드 베이 브릿지\"\n    },\n    \"b2-4\": {\n        \"name\": \"샌프란시스코 시내와 수트로 타워\"\n    },\n    \"4AD99907-9E76-408D-A7FC-8429FF014201\": {\n        \"name\": \"샌프란시스코만과 엠바카데로\"\n    },\n    \"03EC0F5E-CCA8-4E0A-9FEC-5BD1CE151182\": {\n        \"name\": \"남극\"\n    },\n    \"737E9E24-49BE-4104-9B72-F352DE1AD2BF\": {\n        \"name\": \"북아메리카의 오로라\"\n    },\n    \"A837FA8C-C643-4705-AE92-074EFDD067F7\": {\n        \"name\": \"아프리카의 밤\"\n    },\n    \"2F72BC1E-3D76-456C-81EB-842EBA488C27\": {\n        \"name\": \"아프리카와 중동\"\n    },\n    \"12318CCB-3F78-43B7-A854-EFDCCE5312CD\": {\n        \"name\": \"캘리포니아에서 라스베가스까지\"\n    },\n    \"D5CFB2FF-5F8C-4637-816B-3E42FC1229B8\": {\n        \"name\": \"카리브제도\"\n    },\n    \"4F881F8B-A7D9-4FDB-A917-17BF6AC5A589\": {\n        \"name\": \"카리브제도의 낮\"\n    },\n    \"7825C73A-658F-48EE-B14C-EC56673094AC\": {\n        \"name\": \"중국\"\n    },\n    \"E5DB138A-F04E-4619-B896-DE5CB538C534\": {\n        \"name\": \"이탈리아에서 아시아까지\"\n    },\n    \"F439B0A7-D18C-4B14-9681-6520E6A74FE9\": {\n        \"name\": \"이란과 아프가니스탄\"\n    },\n    \"7C643A39-C0B2-4BA0-8BC2-2EAA47CC580E\": {\n        \"name\": \"아일랜드에서 아시아까지\"\n    },\n    \"63C042F0-90EF-4A95-B7CC-CC9A64BF8421\": {\n        \"name\": \"서아프리카에서 알프스까지\"\n    },\n    \"78911B7E-3C69-47AD-B635-9C2486F6301D\": {\n        \"name\": \"뉴질랜드\"\n    },\n    \"E556BBC5-D0A0-4DB1-AC77-BC76E4A526F4\": {\n        \"name\": \"사하라사막과 이탈리아\"\n    },\n    \"64D11DAB-3B57-4F14-AD2F-E59A9282FA44\": {\n        \"name\": \"대서양에서 스페인 그리고 프랑스까지\"\n    },\n    \"81337355-E156-4242-AAF4-711768D30A54\": {\n        \"name\": \"호주\"\n    },\n    \"1088217C-1410-4CF7-BDE9-8F573A4DBCD9\": {\n        \"name\": \"카리브제도에서 중앙아메리카까지\"\n    },\n    \"3C4678E4-4D3D-4A40-8817-77752AEA62EB\": {\n        \"name\": \"나일강 삼각주\"\n    },\n    \"87060EC2-D006-4102-98CC-3005C68BB343\": {\n        \"name\": \"남아프리카에서 북아시아까지\"\n    },\n    \"F07CC61B-30FC-4614-BDAD-3240B61F6793\": {\n        \"name\": \"팔라우의 산호\"\n    },\n    \"6143116D-03BB-485E-864E-A8CF58ACF6F1\": {\n        \"name\": \"남아프리카의 다시마목\"\n    },\n    \"2B30E324-E4FF-4CC1-BA45-A958C2D2B2EC\": {\n        \"name\": \"바라쿠다\"\n    },\n    \"581A4F1A-2B6D-468C-A1BE-6F473F06D10B\": {\n        \"name\": \"불가사리\"\n    },\n    \"687D03A2-18A5-4181-8E85-38F3A13409B9\": {\n        \"name\": \"녹색의 험프헤드 패럿피쉬\"\n    },\n    \"537A4DAB-83B0-4B66-BCD1-05E5DBB4A268\": {\n        \"name\": \"전갱이\"\n    },\n    \"27A37B0F-738D-4644-A7A4-E33E7A6C1175\": {\n        \"name\": \"캘리포니아의 돌고래들\"\n    },\n    \"EB3F48E7-D30F-4079-858F-1A61331D5026\": {\n        \"name\": \"캘리포니아의 다시마목\"\n    },\n    \"CE9B5D5B-B6E7-47C5-8C04-59BF182E98FB\": {\n        \"name\": \"코스타리카의 돌고래들\"\n    },\n    \"58C75C62-3290-47B8-849C-56A583173570\": {\n        \"name\": \"카우노즈레이\"\n    },\n    \"3716DD4B-01C0-4F5B-8DD6-DB771EC472FB\": {\n        \"name\": \"그레이 리프 샤크\"\n    },\n    \"DD47D8E1-CB66-4C12-BFEA-2ADB0D8D1E2E\": {\n        \"name\": \"혹등고래\"\n    },\n    \"82175C1F-153C-4EC8-AE37-2860EA828004\": {\n        \"name\": \"홍해 산호\"\n    },\n    \"391BDF6E-3279-4CE1-9CA5-0F82811452D7\": {\n        \"name\": \"물개들\"\n    },\n    \"BA4ECA11-592F-4727-9221-D2A32A16EB28\": {\n        \"name\": \"팔라우의 해파리 1\"\n    },\n    \"E580E5A5-0888-4BE8-A4CA-F74A18A643C3\": {\n        \"name\": \"팔라우의 해파리 2\"\n    },\n    \"EC3DC957-D4C2-4732-AACE-7D0C0F390EC8\": {\n        \"name\": \"팔라우의 해파리 3\"\n    },\n    \"C7AD3D0A-7EDF-412C-A237-B3C9D27381A1\": {\n        \"name\": \"알래스카의 해파리 1\"\n    },\n    \"C6DC4E54-1130-44F8-AF6F-A551D8E8A181\": {\n        \"name\": \"알래스카의 해파리 2\"\n    },\n    \"149E7795-DBDA-4F5D-B39A-14712F841118\": {\n        \"name\": \"타히티의 물결 1\"\n    },\n    \"8C31B06F-91A4-4F7C-93ED-56146D7F48B9\": {\n        \"name\": \"타히티의 물결 2\"\n    }\n}"
  },
  {
    "path": "Resources/Community/missingvideos.json",
    "content": "{\n    \"assets\" : [\n        {\n            \"pointsOfInterest\" : {\n                \"0\" : \"HK_H004_C001_0\"\n            },\n            \"url-1080-H264\" : \"https:/\\/sylvan.apple.com\\/Videos\\/comp_HK_H004_C001_PSNK_DENOISE_v14_SDR_PS_FINAL_20180731_SDR_2K_AVC.mov\",\n            \"accessibilityLabel\" : \"Hong Kong\",\n            \"id\" : \"64EA30BD-C4B5-4CDD-86D7-DFE47E9CB9AA\",\n            \"url-1080-HDR\" : \"https:\\/\\/sylvan.apple.com\\/Aerials\\/2x\\/Videos\\/comp_HK_H004_C001_PSNK_DENOISE_v14_HDR_PS_FINAL_20180731_HDR_2K_HEVC.mov\",\n            \"url-1080-SDR\" : \"https:\\/\\/sylvan.apple.com\\/Aerials\\/2x\\/Videos\\/comp_HK_H004_C001_PSNK_DENOISE_v14_SDR_PS_FINAL_20180731_SDR_2K_HEVC.mov\",\n            \"url-4K-SDR\" : \"https:\\/\\/sylvan.apple.com\\/Aerials\\/2x\\/Videos\\/comp_HK_H004_C001_PSNK_DENOISE_v14_SDR_PS_FINAL_20180731_SDR_4K_HEVC.mov\",\n            \"url-4K-HDR\" : \"https:\\/\\/sylvan.apple.com\\/Aerials\\/2x\\/Videos\\/comp_HK_H004_C001_PSNK_DENOISE_v14_HDR_PS_FINAL_20180731_HDR_4K_HEVC.mov\"\n        },\n    ]\n}\n"
  },
  {
    "path": "Resources/Community/nl.json",
    "content": "{\n    \"009BA758-7060-4479-8EE8-FB9B40C8FB97\": {\n        \"name\": \"Korea en Japan Nacht\"\n    },\n    \"B1B5DDC5-73C8-4920-8133-BACCE38A08DE\": {\n        \"name\": \"Mexico-stad naar New York\"\n    },\n    \"7719B48A-2005-4011-9280-2F64EEC6FD91\": {\n        \"name\": \"Noord-Californië naar Baja\"\n    },\n    \"B876B645-3955-420E-99DF-60139E451CF3\": {\n        \"name\": \"Wulingyuan Nationaal Park 1\"\n    },\n    \"9CCB8297-E9F5-4699-AE1F-890CFBD5E29C\": {\n        \"name\": \"Longji rijstterrassen\"\n    },\n    \"D5E76230-81A3-4F65-A1BA-51B8CADED625\": {\n        \"name\": \"Wulingyuan Nationaal Park 2\"\n    },\n    \"F0236EC5-EE72-4058-A6CE-1F7D2E8253BF\": {\n        \"name\": \"Chinese Muur 1\"\n    },\n    \"22162A9B-DB90-4517-867C-C676BC3E8E95\": {\n        \"name\": \"Chinese Muur 2\"\n    },\n    \"044AD56C-A107-41B2-90CC-E60CCACFBCF5\": {\n        \"name\": \"Chinese Muur 3\"\n    },\n    \"876D51F4-3D78-4221-8AD2-F9E78C0FD9B9\": {\n        \"name\": \"Sheikh Zayed Road\"\n    },\n    \"E991AC0C-F272-44D8-88F3-05F44EDFE3AE\": {\n        \"name\": \"Jachthaven 1\"\n    },\n    \"00BA71CD-2C54-415A-A68A-8358E677D750\": {\n        \"name\": \"Het centrum\"\n    },\n    \"3FFA2A97-7D28-49EA-AA39-5BC9051B2745\": {\n        \"name\": \"Jachthaven 2\"\n    },\n    \"9680B8EB-CE2A-4395-AF41-402801F4D6A6\": {\n        \"name\": \"Het naderen van Burj Khalifa\"\n    },\n    \"2F11E857-4F77-4476-8033-4A1E4610AFCC\": {\n        \"name\": \"Sheikh Zayed Road\"\n    },\n    \"B8F204CE-6024-49AB-85F9-7CA2F6DCD226\": {\n        \"name\": \"Nuussuaq Peninsula\"\n    },\n    \"2F52E34C-39D4-4AB1-9025-8F7141FAA720\": {\n        \"name\": \"Ilulissat Icefjord\"\n    },\n    \"EE01F02D-1413-436C-AB05-410F224A5B7B\": {\n        \"name\": \"Ilulissat Icefjord\"\n    },\n    \"499995FA-E51A-4ACE-8DFD-BDF8AFF6C943\": {\n        \"name\": \"Waimanu Valley\"\n    },\n    \"12E0343D-2CD9-48EA-AB57-4D680FB6D0C7\": {\n        \"name\": \"Laupāhoehoe Nui\"\n    },\n    \"b2-2\": {\n        \"name\": \"Honopū Valley\"\n    },\n    \"258A6797-CC13-4C3A-AB35-4F25CA3BF474\": {\n        \"name\": \"Pu‘u O ‘Umi\"\n    },\n    \"3D729CFC-9000-48D3-A052-C5BD5B7A6842\": {\n        \"name\": \"De kustlijn van Kohala\"\n    },\n    \"82BD33C9-B6D2-47E7-9C42-AA3B7758921A\": {\n        \"name\": \"Pu‘u O ‘Umi\"\n    },\n    \"FE8E1F9D-59BA-4207-B626-28E34D810D0A\": {\n        \"name\": \"De Victoria-Haven 1\"\n    },\n    \"C8559883-6F3E-4AF2-8960-903710CD47B7\": {\n        \"name\": \"Victoria Peak\"\n    },\n    \"024891DE-B7F6-4187-BFE0-E6D237702EF0\": {\n        \"name\": \"Wan Chai\"\n    },\n    \"64EA30BD-C4B5-4CDD-86D7-DFE47E9CB9AA\": {\n        \"name\": \"De Victoria-Haven 2\"\n    },\n    \"E99FA658-A59A-4A2D-9F3B-58E7BDC71A9A\": {\n        \"name\": \"De Victoria-Haven\"\n    },\n    \"001C94AE-2BA4-4E77-A202-F7DE60E8B1C8\": {\n        \"name\": \"Liwa Oasis 1\"\n    },\n    \"AFA22C08-A486-4CE8-9A13-E355B6C38559\": {\n        \"name\": \"Liwa Oasis 2\"\n    },\n    \"58754319-8709-4AB0-8674-B34F04E7FFE2\": {\n        \"name\": \"Rivier de Theems\"\n    },\n    \"A5AAFF5D-8887-42BB-8AFD-867EF557ED85\": {\n        \"name\": \"Buckingham Palace\"\n    },\n    \"F604AF56-EA77-4960-AEF7-82533CC1A8B3\": {\n        \"name\": \"Rivier de Theems bij zonsondergang\"\n    },\n    \"7F4C26C2-67C2-4C3A-8F07-8A7BF6148C97\": {\n        \"name\": \"Rivier de Theems in de schemering\"\n    },\n    \"CE279831-1CA7-4A83-A97B-FF1E20234396\": {\n        \"name\": \"Los Angeles Int'l Airport\"\n    },\n    \"35693AEA-F8C4-4A80-B77D-C94B20A68956\": {\n        \"name\": \"Harbor Freeway\"\n    },\n    \"92E48DE9-13A1-4172-B560-29B4668A87EE\": {\n        \"name\": \"Santa Monica Beach\"\n    },\n    \"89B1643B-06DD-4DEC-B1B0-774493B0F7B7\": {\n        \"name\": \"Griffith Observatory\"\n    },\n    \"EC67726A-8212-4C5E-83CF-8412932740D2\": {\n        \"name\": \"Hollywood Hills\"\n    },\n    \"F5804DD6-5963-40DA-9FA0-39C0C6E6DEF9\": {\n        \"name\": \"Het centrum\"\n    },\n    \"3BA0CFC7-E460-4B59-A817-B97F9EBB9B89\": {\n        \"name\": \"Central Park\"\n    },\n    \"b1-3\": {\n        \"name\": \"Lower Manhattan\"\n    },\n    \"840FE8E4-D952-4680-B1A7-AC5BACA2C1F8\": {\n        \"name\": \"Upper East Side\"\n    },\n    \"44166C39-8566-4ECA-BD16-43159429B52F\": {\n        \"name\": \"Seventh Avenue\"\n    },\n    \"640DFB00-FBB9-45DA-9444-9F663859F4BC\": {\n        \"name\": \"Lower Manhattan\"\n    },\n    \"b8-2\": {\n        \"name\": \"Marin Headlands\"\n    },\n    \"EE533FBD-90AE-419A-AD13-D7A60E2015D6\": {\n        \"name\": \"Marin Headlands in Fog\"\n    },\n    \"DE851E6D-C2BE-4D9F-AB54-0F9CE994DC51\": {\n        \"name\": \"De baai en de Golden Gate\"\n    },\n    \"b8-3\": {\n        \"name\": \"Alamo Square\"\n    },\n    \"85CE77BF-3413-4A7B-9B0F-732E96229A73\": {\n        \"name\": \"Embarcadero, Market Street\"\n    },\n    \"b4-3\": {\n        \"name\": \"Presidio naar Golden Gate\"\n    },\n    \"72B4390D-DF1D-4D51-B179-229BBAEFFF2C\": {\n        \"name\": \"Golden Gate van SF\"\n    },\n    \"b6-4\": {\n        \"name\": \"Het centrum en de Coit Tower\"\n    },\n    \"29BDF297-EB43-403A-8719-A78DA11A2948\": {\n        \"name\": \"Fisherman's Wharf\"\n    },\n    \"b5-3\": {\n        \"name\": \"Embarcadero, Market Street\"\n    },\n    \"3E94AE98-EAF2-4B09-96E3-452F46BC114E\": {\n        \"name\": \"Bay Bridge\"\n    },\n    \"b2-4\": {\n        \"name\": \"Het centrum en de Sutro Tower\"\n    },\n    \"4AD99907-9E76-408D-A7FC-8429FF014201\": {\n        \"name\": \"Bay en Embarcadero\"\n    },\n    \"03EC0F5E-CCA8-4E0A-9FEC-5BD1CE151182\": {\n        \"name\": \"Antartica\"\n    },\n    \"737E9E24-49BE-4104-9B72-F352DE1AD2BF\": {\n        \"name\": \"Noord-Amerika Aurora\"\n    },\n    \"A837FA8C-C643-4705-AE92-074EFDD067F7\": {\n        \"name\": \"Afrikaanse nacht\"\n    },\n    \"2F72BC1E-3D76-456C-81EB-842EBA488C27\": {\n        \"name\": \"Afrika en het Midden-Oosten\"\n    },\n    \"12318CCB-3F78-43B7-A854-EFDCCE5312CD\": {\n        \"name\": \"Californië naar Vegas\"\n    },\n    \"D5CFB2FF-5F8C-4637-816B-3E42FC1229B8\": {\n        \"name\": \"Caribisch gebied\"\n    },\n    \"4F881F8B-A7D9-4FDB-A917-17BF6AC5A589\": {\n        \"name\": \"Caribische dag\"\n    },\n    \"7825C73A-658F-48EE-B14C-EC56673094AC\": {\n        \"name\": \"China\"\n    },\n    \"E5DB138A-F04E-4619-B896-DE5CB538C534\": {\n        \"name\": \"Italië naar Azië\"\n    },\n    \"F439B0A7-D18C-4B14-9681-6520E6A74FE9\": {\n        \"name\": \"Iran en Afghanistan\"\n    },\n    \"7C643A39-C0B2-4BA0-8BC2-2EAA47CC580E\": {\n        \"name\": \"Ierland naar Azië\"\n    },\n    \"63C042F0-90EF-4A95-B7CC-CC9A64BF8421\": {\n        \"name\": \"West-Afrika naar de Alpen\"\n    },\n    \"78911B7E-3C69-47AD-B635-9C2486F6301D\": {\n        \"name\": \"Nieuw-Zeeland\"\n    },\n    \"E556BBC5-D0A0-4DB1-AC77-BC76E4A526F4\": {\n        \"name\": \"Sahara en Italië\"\n    },\n    \"64D11DAB-3B57-4F14-AD2F-E59A9282FA44\": {\n        \"name\": \"Atlantic Ocean to Spain and France\"\n    },\n    \"81337355-E156-4242-AAF4-711768D30A54\": {\n        \"name\": \"Australia\"\n    },\n    \"1088217C-1410-4CF7-BDE9-8F573A4DBCD9\": {\n        \"name\": \"Caribbean to Central America\"\n    },\n    \"3C4678E4-4D3D-4A40-8817-77752AEA62EB\": {\n        \"name\": \"Nile Delta\"\n    },\n    \"87060EC2-D006-4102-98CC-3005C68BB343\": {\n        \"name\": \"South Africa to North Asia\"\n    },\n    \"F07CC61B-30FC-4614-BDAD-3240B61F6793\": {\n        \"name\": \"Palau Coral\"\n    },\n    \"6143116D-03BB-485E-864E-A8CF58ACF6F1\": {\n        \"name\": \"South African Kelp\"\n    },\n    \"2B30E324-E4FF-4CC1-BA45-A958C2D2B2EC\": {\n        \"name\": \"Barracuda\"\n    },\n    \"581A4F1A-2B6D-468C-A1BE-6F473F06D10B\": {\n        \"name\": \"Sea Stars\"\n    },\n    \"687D03A2-18A5-4181-8E85-38F3A13409B9\": {\n        \"name\": \"Bumpheads\"\n    },\n    \"537A4DAB-83B0-4B66-BCD1-05E5DBB4A268\": {\n        \"name\": \"Jacks\"\n    },\n    \"27A37B0F-738D-4644-A7A4-E33E7A6C1175\": {\n        \"name\": \"California Dolphins\"\n    },\n    \"EB3F48E7-D30F-4079-858F-1A61331D5026\": {\n        \"name\": \"California Kelp Forest\"\n    },\n    \"CE9B5D5B-B6E7-47C5-8C04-59BF182E98FB\": {\n        \"name\": \"Costa Rica Dolphins\"\n    },\n    \"58C75C62-3290-47B8-849C-56A583173570\": {\n        \"name\": \"Cownose Rays\"\n    },\n    \"3716DD4B-01C0-4F5B-8DD6-DB771EC472FB\": {\n        \"name\": \"Gray Reef Sharks\"\n    },\n    \"DD47D8E1-CB66-4C12-BFEA-2ADB0D8D1E2E\": {\n        \"name\": \"Humpback Whale\"\n    },\n    \"82175C1F-153C-4EC8-AE37-2860EA828004\": {\n        \"name\": \"Red Sea Coral\"\n    },\n    \"391BDF6E-3279-4CE1-9CA5-0F82811452D7\": {\n        \"name\": \"Seals\"\n    },\n    \"BA4ECA11-592F-4727-9221-D2A32A16EB28\": {\n        \"name\": \"Palau Jellies 1\"\n    },\n    \"E580E5A5-0888-4BE8-A4CA-F74A18A643C3\": {\n        \"name\": \"Palau Jellies 2\"\n    },\n    \"EC3DC957-D4C2-4732-AACE-7D0C0F390EC8\": {\n        \"name\": \"Palau Jellies 3\"\n    },\n    \"C7AD3D0A-7EDF-412C-A237-B3C9D27381A1\": {\n        \"name\": \"Alaskan Jellies 1\"\n    },\n    \"C6DC4E54-1130-44F8-AF6F-A551D8E8A181\": {\n        \"name\": \"Alaskan Jellies 2\"\n    },\n    \"149E7795-DBDA-4F5D-B39A-14712F841118\": {\n        \"name\": \"Tahiti Waves 1\"\n    },\n    \"8C31B06F-91A4-4F7C-93ED-56146D7F48B9\": {\n        \"name\": \"Tahiti Waves 2\"\n    }\n}"
  },
  {
    "path": "Resources/Community/pl.json",
    "content": "{\n    \"009BA758-7060-4479-8EE8-FB9B40C8FB97\": {\n        \"name\": \"Korea i Japonia\"\n    },\n    \"B1B5DDC5-73C8-4920-8133-BACCE38A08DE\": {\n        \"name\": \"Od Mexico City do Nowego Jorku\"\n    },\n    \"7719B48A-2005-4011-9280-2F64EEC6FD91\": {\n        \"name\": \"Od Kalifornii do Baja\"\n    },\n    \"B876B645-3955-420E-99DF-60139E451CF3\": {\n        \"name\": \"Park Narodowy Wulingyuan 1\"\n    },\n    \"9CCB8297-E9F5-4699-AE1F-890CFBD5E29C\": {\n        \"name\": \"Tarasy ryżowe Longji\"\n    },\n    \"D5E76230-81A3-4F65-A1BA-51B8CADED625\": {\n        \"name\": \"Park Narodowy Wulingyuan 2\"\n    },\n    \"F0236EC5-EE72-4058-A6CE-1F7D2E8253BF\": {\n        \"name\": \"Wielki Mur 1\"\n    },\n    \"22162A9B-DB90-4517-867C-C676BC3E8E95\": {\n        \"name\": \"Wielki Mur 2\"\n    },\n    \"044AD56C-A107-41B2-90CC-E60CCACFBCF5\": {\n        \"name\": \"Wielki Mur 3\"\n    },\n    \"876D51F4-3D78-4221-8AD2-F9E78C0FD9B9\": {\n        \"name\": \"Droga Sheikh Zayed\"\n    },\n    \"E991AC0C-F272-44D8-88F3-05F44EDFE3AE\": {\n        \"name\": \"Przystań 1\"\n    },\n    \"00BA71CD-2C54-415A-A68A-8358E677D750\": {\n        \"name\": \"Śródmieście\"\n    },\n    \"3FFA2A97-7D28-49EA-AA39-5BC9051B2745\": {\n        \"name\": \"Przystań 2\"\n    },\n    \"9680B8EB-CE2A-4395-AF41-402801F4D6A6\": {\n        \"name\": \"Zbliżając się do Burj Khalifa\"\n    },\n    \"2F11E857-4F77-4476-8033-4A1E4610AFCC\": {\n        \"name\": \"Droga Sheikh Zayed\"\n    },\n    \"B8F204CE-6024-49AB-85F9-7CA2F6DCD226\": {\n        \"name\": \"Półwysep Nuussuaq\"\n    },\n    \"2F52E34C-39D4-4AB1-9025-8F7141FAA720\": {\n        \"name\": \"Fjord lodowy w llulissat\"\n    },\n    \"EE01F02D-1413-436C-AB05-410F224A5B7B\": {\n        \"name\": \"Fjord lodowy w llulissat\"\n    },\n    \"499995FA-E51A-4ACE-8DFD-BDF8AFF6C943\": {\n        \"name\": \"Dolina Waimanu\"\n    },\n    \"12E0343D-2CD9-48EA-AB57-4D680FB6D0C7\": {\n        \"name\": \"Laupāhoehoe Nui\"\n    },\n    \"b2-2\": {\n        \"name\": \"Dolina Honopū\"\n    },\n    \"258A6797-CC13-4C3A-AB35-4F25CA3BF474\": {\n        \"name\": \"Pu'u O 'Umi\"\n    },\n    \"3D729CFC-9000-48D3-A052-C5BD5B7A6842\": {\n        \"name\": \"Wybrzeże Kohala\"\n    },\n    \"82BD33C9-B6D2-47E7-9C42-AA3B7758921A\": {\n        \"name\": \"Pu'u O 'Umi\"\n    },\n    \"FE8E1F9D-59BA-4207-B626-28E34D810D0A\": {\n        \"name\": \"Port Wiktorii 1\"\n    },\n    \"C8559883-6F3E-4AF2-8960-903710CD47B7\": {\n        \"name\": \"Szczyt Wiktorii\"\n    },\n    \"024891DE-B7F6-4187-BFE0-E6D237702EF0\": {\n        \"name\": \"Wan Chai\"\n    },\n    \"64EA30BD-C4B5-4CDD-86D7-DFE47E9CB9AA\": {\n        \"name\": \"Port Wiktorii 2\"\n    },\n    \"E99FA658-A59A-4A2D-9F3B-58E7BDC71A9A\": {\n        \"name\": \"Port Wiktorii\"\n    },\n    \"001C94AE-2BA4-4E77-A202-F7DE60E8B1C8\": {\n        \"name\": \"Oaza Liwa 1\"\n    },\n    \"AFA22C08-A486-4CE8-9A13-E355B6C38559\": {\n        \"name\": \"Oaza Liwa 2\"\n    },\n    \"58754319-8709-4AB0-8674-B34F04E7FFE2\": {\n        \"name\": \"Tamiza\"\n    },\n    \"A5AAFF5D-8887-42BB-8AFD-867EF557ED85\": {\n        \"name\": \"Pałac Buckingham\"\n    },\n    \"F604AF56-EA77-4960-AEF7-82533CC1A8B3\": {\n        \"name\": \"Rzeka Tamiza podczas zachodu słońca\"\n    },\n    \"7F4C26C2-67C2-4C3A-8F07-8A7BF6148C97\": {\n        \"name\": \"Tamiza o zmierzchu\"\n    },\n    \"CE279831-1CA7-4A83-A97B-FF1E20234396\": {\n        \"name\": \"Międzynarodowy port lotniczy Los Angeles\"\n    },\n    \"35693AEA-F8C4-4A80-B77D-C94B20A68956\": {\n        \"name\": \"Harbor Freeway\"\n    },\n    \"92E48DE9-13A1-4172-B560-29B4668A87EE\": {\n        \"name\": \"Plaża Santa Monica\"\n    },\n    \"89B1643B-06DD-4DEC-B1B0-774493B0F7B7\": {\n        \"name\": \"Obserwatorium Griffitha\"\n    },\n    \"EC67726A-8212-4C5E-83CF-8412932740D2\": {\n        \"name\": \"Wzgórza Hollywood\"\n    },\n    \"F5804DD6-5963-40DA-9FA0-39C0C6E6DEF9\": {\n        \"name\": \"Śródmieście\"\n    },\n    \"3BA0CFC7-E460-4B59-A817-B97F9EBB9B89\": {\n        \"name\": \"Central Park\"\n    },\n    \"b1-3\": {\n        \"name\": \"Dolny Manhattan\"\n    },\n    \"840FE8E4-D952-4680-B1A7-AC5BACA2C1F8\": {\n        \"name\": \"Upper East Side\"\n    },\n    \"44166C39-8566-4ECA-BD16-43159429B52F\": {\n        \"name\": \"Siódma Aleja\"\n    },\n    \"640DFB00-FBB9-45DA-9444-9F663859F4BC\": {\n        \"name\": \"Dolny Manhattan\"\n    },\n    \"b8-2\": {\n        \"name\": \"Marin Headlands\"\n    },\n    \"EE533FBD-90AE-419A-AD13-D7A60E2015D6\": {\n        \"name\": \"Marin Headlands we mgle\"\n    },\n    \"DE851E6D-C2BE-4D9F-AB54-0F9CE994DC51\": {\n        \"name\": \"Zatoka i Most Golden Gate\"\n    },\n    \"b8-3\": {\n        \"name\": \"Plac Alama\"\n    },\n    \"85CE77BF-3413-4A7B-9B0F-732E96229A73\": {\n        \"name\": \"Embarcadero, Market Street\"\n    },\n    \"b4-3\": {\n        \"name\": \"Od Prezydium do Mostu Golden Gate\"\n    },\n    \"72B4390D-DF1D-4D51-B179-229BBAEFFF2C\": {\n        \"name\": \"Most Golden Gate od strony San Franciso\"\n    },\n    \"b6-4\": {\n        \"name\": \"Śródmieście i Wieża Coit\"\n    },\n    \"29BDF297-EB43-403A-8719-A78DA11A2948\": {\n        \"name\": \"Fisherman's Wharf\"\n    },\n    \"b5-3\": {\n        \"name\": \"Embarcadero, Market Street\"\n    },\n    \"3E94AE98-EAF2-4B09-96E3-452F46BC114E\": {\n        \"name\": \"Most Zatokowy\"\n    },\n    \"b2-4\": {\n        \"name\": \"Śródmieście i wieża Sutro\"\n    },\n    \"4AD99907-9E76-408D-A7FC-8429FF014201\": {\n        \"name\": \"Zatoka San Francisco i Embarcadero\"\n    },\n    \"03EC0F5E-CCA8-4E0A-9FEC-5BD1CE151182\": {\n        \"name\": \"Antarktyda\"\n    },\n    \"737E9E24-49BE-4104-9B72-F352DE1AD2BF\": {\n        \"name\": \"Zorza nad Ameryką Północną\"\n    },\n    \"A837FA8C-C643-4705-AE92-074EFDD067F7\": {\n        \"name\": \"Noc afrykańska\"\n    },\n    \"2F72BC1E-3D76-456C-81EB-842EBA488C27\": {\n        \"name\": \"Afryka i Bliski Wschód\"\n    },\n    \"12318CCB-3F78-43B7-A854-EFDCCE5312CD\": {\n        \"name\": \"Od Kalifornii do Vegas\"\n    },\n    \"D5CFB2FF-5F8C-4637-816B-3E42FC1229B8\": {\n        \"name\": \"Karaiby\"\n    },\n    \"4F881F8B-A7D9-4FDB-A917-17BF6AC5A589\": {\n        \"name\": \"Karaiby za dnia\"\n    },\n    \"7825C73A-658F-48EE-B14C-EC56673094AC\": {\n        \"name\": \"Chiny\"\n    },\n    \"E5DB138A-F04E-4619-B896-DE5CB538C534\": {\n        \"name\": \"Od Włoch do Azji\"\n    },\n    \"F439B0A7-D18C-4B14-9681-6520E6A74FE9\": {\n        \"name\": \"Iran i Afganistan\"\n    },\n    \"7C643A39-C0B2-4BA0-8BC2-2EAA47CC580E\": {\n        \"name\": \"Od Irlandii do Azji\"\n    },\n    \"63C042F0-90EF-4A95-B7CC-CC9A64BF8421\": {\n        \"name\": \"Od Afryki Zachodniej do Alp\"\n    },\n    \"78911B7E-3C69-47AD-B635-9C2486F6301D\": {\n        \"name\": \"Nowa Zelandia\"\n    },\n    \"E556BBC5-D0A0-4DB1-AC77-BC76E4A526F4\": {\n        \"name\": \"Sahara i Włochy\"\n    },\n    \"64D11DAB-3B57-4F14-AD2F-E59A9282FA44\": {\n        \"name\": \"Od Oceanu Atlantyckiego do Hiszpanii i Francji\"\n    },\n    \"81337355-E156-4242-AAF4-711768D30A54\": {\n        \"name\": \"Australia\"\n    },\n    \"1088217C-1410-4CF7-BDE9-8F573A4DBCD9\": {\n        \"name\": \"Od Karaibów do Ameryki Środkowej\"\n    },\n    \"3C4678E4-4D3D-4A40-8817-77752AEA62EB\": {\n        \"name\": \"Delta Nilu\"\n    },\n    \"87060EC2-D006-4102-98CC-3005C68BB343\": {\n        \"name\": \"Od Afryki Południowej do Azji Północnej\"\n    },\n    \"F07CC61B-30FC-4614-BDAD-3240B61F6793\": {\n        \"name\": \"Rafa koralowa Palau\"\n    },\n    \"6143116D-03BB-485E-864E-A8CF58ACF6F1\": {\n        \"name\": \"Wodorosty południowoafrykańskie\"\n    },\n    \"2B30E324-E4FF-4CC1-BA45-A958C2D2B2EC\": {\n        \"name\": \"Barrakuda\"\n    },\n    \"581A4F1A-2B6D-468C-A1BE-6F473F06D10B\": {\n        \"name\": \"Gwiazdy morskie\"\n    },\n    \"687D03A2-18A5-4181-8E85-38F3A13409B9\": {\n        \"name\": \"Bolbometopon muricatum\"\n    },\n    \"537A4DAB-83B0-4B66-BCD1-05E5DBB4A268\": {\n        \"name\": \"Karanks smugowy\"\n    },\n    \"27A37B0F-738D-4644-A7A4-E33E7A6C1175\": {\n        \"name\": \"Delfiny kalifornijskie\"\n    },\n    \"EB3F48E7-D30F-4079-858F-1A61331D5026\": {\n        \"name\": \"Las Kelp w Kalifornii\"\n    },\n    \"CE9B5D5B-B6E7-47C5-8C04-59BF182E98FB\": {\n        \"name\": \"Delfiny kostarykańskie\"\n    },\n    \"58C75C62-3290-47B8-849C-56A583173570\": {\n        \"name\": \"Płaszczka karbogłowa\"\n    },\n    \"3716DD4B-01C0-4F5B-8DD6-DB771EC472FB\": {\n        \"name\": \"Rekin szary rafowy\"\n    },\n    \"DD47D8E1-CB66-4C12-BFEA-2ADB0D8D1E2E\": {\n        \"name\": \"Długopłetwiec oceaniczny\"\n    },\n    \"82175C1F-153C-4EC8-AE37-2860EA828004\": {\n        \"name\": \"Koralowce Morza Czerwonego\"\n    },\n    \"391BDF6E-3279-4CE1-9CA5-0F82811452D7\": {\n        \"name\": \"Płetwonogie\"\n    },\n    \"BA4ECA11-592F-4727-9221-D2A32A16EB28\": {\n        \"name\": \"Meduzy Palau 1\"\n    },\n    \"E580E5A5-0888-4BE8-A4CA-F74A18A643C3\": {\n        \"name\": \"Meduzy Palau 2\"\n    },\n    \"EC3DC957-D4C2-4732-AACE-7D0C0F390EC8\": {\n        \"name\": \"Meduzy Palau 3\"\n    },\n    \"C7AD3D0A-7EDF-412C-A237-B3C9D27381A1\": {\n        \"name\": \"Meduzy Alaskie 1\"\n    },\n    \"C6DC4E54-1130-44F8-AF6F-A551D8E8A181\": {\n        \"name\": \"Meduzy Alaskie 2\"\n    },\n    \"149E7795-DBDA-4F5D-B39A-14712F841118\": {\n        \"name\": \"Fale Tahiti 1\"\n    },\n    \"8C31B06F-91A4-4F7C-93ED-56146D7F48B9\": {\n        \"name\": \"Fale Tahiti 2\"\n    }\n}"
  },
  {
    "path": "Resources/Community/pt.json",
    "content": "{\n    \"009BA758-7060-4479-8EE8-FB9B40C8FB97\": {\n        \"name\": \"Coreia e Japão a noite\"\n    },\n    \"B1B5DDC5-73C8-4920-8133-BACCE38A08DE\": {\n        \"name\": \"Da Cidade do México para Nova York\"\n    },\n    \"7719B48A-2005-4011-9280-2F64EEC6FD91\": {\n        \"name\": \"Do Norte da Califórnia para Baja\"\n    },\n    \"B876B645-3955-420E-99DF-60139E451CF3\": {\n        \"name\": \"Parque Nacional Wulingyuan 1\"\n    },\n    \"9CCB8297-E9F5-4699-AE1F-890CFBD5E29C\": {\n        \"name\": \"Terraços de Arroz de Longji\"\n    },\n    \"D5E76230-81A3-4F65-A1BA-51B8CADED625\": {\n        \"name\": \"Parque Nacional Wulingyuan 2\"\n    },\n    \"F0236EC5-EE72-4058-A6CE-1F7D2E8253BF\": {\n        \"name\": \"Muralha da China 1\"\n    },\n    \"22162A9B-DB90-4517-867C-C676BC3E8E95\": {\n        \"name\": \"Muralha da China 2\"\n    },\n    \"044AD56C-A107-41B2-90CC-E60CCACFBCF5\": {\n        \"name\": \"Muralha da China 3\"\n    },\n    \"876D51F4-3D78-4221-8AD2-F9E78C0FD9B9\": {\n        \"name\": \"Sheikh Zayed Road\"\n    },\n    \"E991AC0C-F272-44D8-88F3-05F44EDFE3AE\": {\n        \"name\": \"Marina 1\"\n    },\n    \"00BA71CD-2C54-415A-A68A-8358E677D750\": {\n        \"name\": \"Centro da cidade\"\n    },\n    \"3FFA2A97-7D28-49EA-AA39-5BC9051B2745\": {\n        \"name\": \"Marina 2\"\n    },\n    \"9680B8EB-CE2A-4395-AF41-402801F4D6A6\": {\n        \"name\": \"Aproximando-se do Burj Khalifa\"\n    },\n    \"2F11E857-4F77-4476-8033-4A1E4610AFCC\": {\n        \"name\": \"Estrada Sheikh Zayed\"\n    },\n    \"B8F204CE-6024-49AB-85F9-7CA2F6DCD226\": {\n        \"name\": \"Península de Nuussuaq\"\n    },\n    \"2F52E34C-39D4-4AB1-9025-8F7141FAA720\": {\n        \"name\": \"Fiorde de gelo de Ilulissat\"\n    },\n    \"EE01F02D-1413-436C-AB05-410F224A5B7B\": {\n        \"name\": \"Fiorde de gelo de Ilulissat\"\n    },\n    \"499995FA-E51A-4ACE-8DFD-BDF8AFF6C943\": {\n        \"name\": \"Vale de Waimanu\"\n    },\n    \"12E0343D-2CD9-48EA-AB57-4D680FB6D0C7\": {\n        \"name\": \"Laupāhoehoe Nui\"\n    },\n    \"b2-2\": {\n        \"name\": \"Honopū Vale\"\n    },\n    \"258A6797-CC13-4C3A-AB35-4F25CA3BF474\": {\n        \"name\": \"Pu'u O 'Umi\"\n    },\n    \"3D729CFC-9000-48D3-A052-C5BD5B7A6842\": {\n        \"name\": \"Costa de Kohala\"\n    },\n    \"82BD33C9-B6D2-47E7-9C42-AA3B7758921A\": {\n        \"name\": \"Pu'u O 'Umi\"\n    },\n    \"FE8E1F9D-59BA-4207-B626-28E34D810D0A\": {\n        \"name\": \"Victoria Harbour 1\"\n    },\n    \"C8559883-6F3E-4AF2-8960-903710CD47B7\": {\n        \"name\": \"Victoria Peak\"\n    },\n    \"024891DE-B7F6-4187-BFE0-E6D237702EF0\": {\n        \"name\": \"Wan Chai\"\n    },\n    \"64EA30BD-C4B5-4CDD-86D7-DFE47E9CB9AA\": {\n        \"name\": \"Victoria Harbour 2\"\n    },\n    \"E99FA658-A59A-4A2D-9F3B-58E7BDC71A9A\": {\n        \"name\": \"Victoria Harbour\"\n    },\n    \"001C94AE-2BA4-4E77-A202-F7DE60E8B1C8\": {\n        \"name\": \"Liwa Oasis 1\"\n    },\n    \"AFA22C08-A486-4CE8-9A13-E355B6C38559\": {\n        \"name\": \"Liwa Oasis 2\"\n    },\n    \"58754319-8709-4AB0-8674-B34F04E7FFE2\": {\n        \"name\": \"Rio Tamisa\"\n    },\n    \"A5AAFF5D-8887-42BB-8AFD-867EF557ED85\": {\n        \"name\": \"Palácio de Buckingham\"\n    },\n    \"F604AF56-EA77-4960-AEF7-82533CC1A8B3\": {\n        \"name\": \"Rio Tamisa ao pôr do sol\"\n    },\n    \"7F4C26C2-67C2-4C3A-8F07-8A7BF6148C97\": {\n        \"name\": \"Rio Tamisa ao Anoitecer\"\n    },\n    \"CE279831-1CA7-4A83-A97B-FF1E20234396\": {\n        \"name\": \"Aeroporto Internacional de Los Angeles\"\n    },\n    \"35693AEA-F8C4-4A80-B77D-C94B20A68956\": {\n        \"name\": \"Harbor Freeway (Rota 110)\"\n    },\n    \"92E48DE9-13A1-4172-B560-29B4668A87EE\": {\n        \"name\": \"Praia de Santa Monica\"\n    },\n    \"89B1643B-06DD-4DEC-B1B0-774493B0F7B7\": {\n        \"name\": \"Observatório Griffith\"\n    },\n    \"EC67726A-8212-4C5E-83CF-8412932740D2\": {\n        \"name\": \"Hollywood Hills\"\n    },\n    \"F5804DD6-5963-40DA-9FA0-39C0C6E6DEF9\": {\n        \"name\": \"Centro da cidade\"\n    },\n    \"3BA0CFC7-E460-4B59-A817-B97F9EBB9B89\": {\n        \"name\": \"Central Park\"\n    },\n    \"b1-3\": {\n        \"name\": \"Baixa Manhattan\"\n    },\n    \"840FE8E4-D952-4680-B1A7-AC5BACA2C1F8\": {\n        \"name\": \"Upper East Side\"\n    },\n    \"44166C39-8566-4ECA-BD16-43159429B52F\": {\n        \"name\": \"Sétima Avenida\"\n    },\n    \"640DFB00-FBB9-45DA-9444-9F663859F4BC\": {\n        \"name\": \"Baixa Manhattan\"\n    },\n    \"b8-2\": {\n        \"name\": \"Marin Headlands\"\n    },\n    \"EE533FBD-90AE-419A-AD13-D7A60E2015D6\": {\n        \"name\": \"Marin Headlands com Neblina\"\n    },\n    \"DE851E6D-C2BE-4D9F-AB54-0F9CE994DC51\": {\n        \"name\": \"Baía de SF e Golden Gate Bridge\"\n    },\n    \"b8-3\": {\n        \"name\": \"Alamo Square\"\n    },\n    \"85CE77BF-3413-4A7B-9B0F-732E96229A73\": {\n        \"name\": \"Embarcadero, Market Street\"\n    },\n    \"b4-3\": {\n        \"name\": \"Do Presídio para a Golden Gate\"\n    },\n    \"72B4390D-DF1D-4D51-B179-229BBAEFFF2C\": {\n        \"name\": \"Ponte Golden Gate em SF\"\n    },\n    \"b6-4\": {\n        \"name\": \"Centro da cidade e Coit Tower\"\n    },\n    \"29BDF297-EB43-403A-8719-A78DA11A2948\": {\n        \"name\": \"Fisherman’s Wharf\"\n    },\n    \"b5-3\": {\n        \"name\": \"Embarcadero, Market Street\"\n    },\n    \"3E94AE98-EAF2-4B09-96E3-452F46BC114E\": {\n        \"name\": \"Ponte São Francisco\"\n    },\n    \"b2-4\": {\n        \"name\": \"Centro da cidade e Torre Sutro\"\n    },\n    \"4AD99907-9E76-408D-A7FC-8429FF014201\": {\n        \"name\": \"Baía e Embarcadero\"\n    },\n    \"03EC0F5E-CCA8-4E0A-9FEC-5BD1CE151182\": {\n        \"name\": \"Antartica\"\n    },\n    \"737E9E24-49BE-4104-9B72-F352DE1AD2BF\": {\n        \"name\": \"Aurora Borealis (América do Norte)\"\n    },\n    \"A837FA8C-C643-4705-AE92-074EFDD067F7\": {\n        \"name\": \"África a noite\"\n    },\n    \"2F72BC1E-3D76-456C-81EB-842EBA488C27\": {\n        \"name\": \"África e o Oriente Médio\"\n    },\n    \"12318CCB-3F78-43B7-A854-EFDCCE5312CD\": {\n        \"name\": \"Da Califórnia para Vegas\"\n    },\n    \"D5CFB2FF-5F8C-4637-816B-3E42FC1229B8\": {\n        \"name\": \"Caribe\"\n    },\n    \"4F881F8B-A7D9-4FDB-A917-17BF6AC5A589\": {\n        \"name\": \"Caribe de dia\"\n    },\n    \"7825C73A-658F-48EE-B14C-EC56673094AC\": {\n        \"name\": \"China\"\n    },\n    \"E5DB138A-F04E-4619-B896-DE5CB538C534\": {\n        \"name\": \"Da Itália para a Ásia\"\n    },\n    \"F439B0A7-D18C-4B14-9681-6520E6A74FE9\": {\n        \"name\": \"Irã e Afeganistão\"\n    },\n    \"7C643A39-C0B2-4BA0-8BC2-2EAA47CC580E\": {\n        \"name\": \"Da Irlanda para a Ásia\"\n    },\n    \"63C042F0-90EF-4A95-B7CC-CC9A64BF8421\": {\n        \"name\": \"Da África Ocidental para os Alpes\"\n    },\n    \"78911B7E-3C69-47AD-B635-9C2486F6301D\": {\n        \"name\": \"Nova Zelândia\"\n    },\n    \"E556BBC5-D0A0-4DB1-AC77-BC76E4A526F4\": {\n        \"name\": \"Deserto do Saara e Itália\"\n    },\n    \"64D11DAB-3B57-4F14-AD2F-E59A9282FA44\": {\n        \"name\": \"Do Oceano Atlântico à Espanha e França\"\n    },\n    \"81337355-E156-4242-AAF4-711768D30A54\": {\n        \"name\": \"Austrália\"\n    },\n    \"1088217C-1410-4CF7-BDE9-8F573A4DBCD9\": {\n        \"name\": \"Do Caribe para a América Central\"\n    },\n    \"3C4678E4-4D3D-4A40-8817-77752AEA62EB\": {\n        \"name\": \"Delta do Nilo\"\n    },\n    \"87060EC2-D006-4102-98CC-3005C68BB343\": {\n        \"name\": \"Da África do Sul para o Norte da Ásia\"\n    },\n    \"F07CC61B-30FC-4614-BDAD-3240B61F6793\": {\n        \"name\": \"Corais em Palau\"\n    },\n    \"6143116D-03BB-485E-864E-A8CF58ACF6F1\": {\n        \"name\": \"Algas na África do Sul\"\n    },\n    \"2B30E324-E4FF-4CC1-BA45-A958C2D2B2EC\": {\n        \"name\": \"Barracudas\"\n    },\n    \"581A4F1A-2B6D-468C-A1BE-6F473F06D10B\": {\n        \"name\": \"Estrelas do mar\"\n    },\n    \"687D03A2-18A5-4181-8E85-38F3A13409B9\": {\n        \"name\": \"Cardume de Peixe Papagaio Cabeçudo\"\n    },\n    \"537A4DAB-83B0-4B66-BCD1-05E5DBB4A268\": {\n        \"name\": \"Cardume de Sargento\"\n    },\n    \"27A37B0F-738D-4644-A7A4-E33E7A6C1175\": {\n        \"name\": \"Golfinhos na Califórnia\"\n    },\n    \"EB3F48E7-D30F-4079-858F-1A61331D5026\": {\n        \"name\": \"Floresta de Algas da Califórnia\"\n    },\n    \"CE9B5D5B-B6E7-47C5-8C04-59BF182E98FB\": {\n        \"name\": \"Golfinhos da Costa Rica\"\n    },\n    \"58C75C62-3290-47B8-849C-56A583173570\": {\n        \"name\": \"Arraias do mar\"\n    },\n    \"3716DD4B-01C0-4F5B-8DD6-DB771EC472FB\": {\n        \"name\": \"Tubarões Cinzento dos Recifes\"\n    },\n    \"DD47D8E1-CB66-4C12-BFEA-2ADB0D8D1E2E\": {\n        \"name\": \"Baleia Jubarte\"\n    },\n    \"82175C1F-153C-4EC8-AE37-2860EA828004\": {\n        \"name\": \"Coral do Mar Vermelho\"\n    },\n    \"391BDF6E-3279-4CE1-9CA5-0F82811452D7\": {\n        \"name\": \"Focas\"\n    },\n    \"BA4ECA11-592F-4727-9221-D2A32A16EB28\": {\n        \"name\": \"Águas-vivas em Palau 1\"\n    },\n    \"E580E5A5-0888-4BE8-A4CA-F74A18A643C3\": {\n        \"name\": \"Águas-vivas em Palau 2\"\n    },\n    \"EC3DC957-D4C2-4732-AACE-7D0C0F390EC8\": {\n        \"name\": \"Águas-vivas em Palau 3\"\n    },\n    \"C7AD3D0A-7EDF-412C-A237-B3C9D27381A1\": {\n        \"name\": \"Águas-vivas no Alasca 1\"\n    },\n    \"C6DC4E54-1130-44F8-AF6F-A551D8E8A181\": {\n        \"name\": \"Águas-vivas no Alasca 2\"\n    },\n    \"149E7795-DBDA-4F5D-B39A-14712F841118\": {\n        \"name\": \"Ondas do Taiti 1\"\n    },\n    \"8C31B06F-91A4-4F7C-93ED-56146D7F48B9\": {\n        \"name\": \"Ondas do Taiti 2\"\n    }\n}"
  },
  {
    "path": "Resources/Community/pt_BR.json",
    "content": "{\n    \"009BA758-7060-4479-8EE8-FB9B40C8FB97\": {\n        \"name\": \"Coreia e Japão a noite\"\n    },\n    \"B1B5DDC5-73C8-4920-8133-BACCE38A08DE\": {\n        \"name\": \"Da Cidade do México para Nova York\"\n    },\n    \"7719B48A-2005-4011-9280-2F64EEC6FD91\": {\n        \"name\": \"Do Norte da Califórnia para Baja\"\n    },\n    \"B876B645-3955-420E-99DF-60139E451CF3\": {\n        \"name\": \"Parque Nacional Wulingyuan 1\"\n    },\n    \"9CCB8297-E9F5-4699-AE1F-890CFBD5E29C\": {\n        \"name\": \"Terraços de Arroz de Longji\"\n    },\n    \"D5E76230-81A3-4F65-A1BA-51B8CADED625\": {\n        \"name\": \"Parque Nacional Wulingyuan 2\"\n    },\n    \"F0236EC5-EE72-4058-A6CE-1F7D2E8253BF\": {\n        \"name\": \"Muralha da China 1\"\n    },\n    \"22162A9B-DB90-4517-867C-C676BC3E8E95\": {\n        \"name\": \"Muralha da China 2\"\n    },\n    \"044AD56C-A107-41B2-90CC-E60CCACFBCF5\": {\n        \"name\": \"Muralha da China 3\"\n    },\n    \"876D51F4-3D78-4221-8AD2-F9E78C0FD9B9\": {\n        \"name\": \"Sheikh Zayed Road\"\n    },\n    \"E991AC0C-F272-44D8-88F3-05F44EDFE3AE\": {\n        \"name\": \"Marina 1\"\n    },\n    \"00BA71CD-2C54-415A-A68A-8358E677D750\": {\n        \"name\": \"Centro da cidade\"\n    },\n    \"3FFA2A97-7D28-49EA-AA39-5BC9051B2745\": {\n        \"name\": \"Marina 2\"\n    },\n    \"9680B8EB-CE2A-4395-AF41-402801F4D6A6\": {\n        \"name\": \"Aproximando-se do Burj Khalifa\"\n    },\n    \"2F11E857-4F77-4476-8033-4A1E4610AFCC\": {\n        \"name\": \"Estrada Sheikh Zayed\"\n    },\n    \"B8F204CE-6024-49AB-85F9-7CA2F6DCD226\": {\n        \"name\": \"Península de Nuussuaq\"\n    },\n    \"2F52E34C-39D4-4AB1-9025-8F7141FAA720\": {\n        \"name\": \"Fiorde de gelo de Ilulissat\"\n    },\n    \"EE01F02D-1413-436C-AB05-410F224A5B7B\": {\n        \"name\": \"Fiorde de gelo de Ilulissat\"\n    },\n    \"499995FA-E51A-4ACE-8DFD-BDF8AFF6C943\": {\n        \"name\": \"Vale de Waimanu\"\n    },\n    \"12E0343D-2CD9-48EA-AB57-4D680FB6D0C7\": {\n        \"name\": \"Laupāhoehoe Nui\"\n    },\n    \"b2-2\": {\n        \"name\": \"Honopū Vale\"\n    },\n    \"258A6797-CC13-4C3A-AB35-4F25CA3BF474\": {\n        \"name\": \"Pu'u O 'Umi\"\n    },\n    \"3D729CFC-9000-48D3-A052-C5BD5B7A6842\": {\n        \"name\": \"Costa de Kohala\"\n    },\n    \"82BD33C9-B6D2-47E7-9C42-AA3B7758921A\": {\n        \"name\": \"Pu'u O 'Umi\"\n    },\n    \"FE8E1F9D-59BA-4207-B626-28E34D810D0A\": {\n        \"name\": \"Victoria Harbour 1\"\n    },\n    \"C8559883-6F3E-4AF2-8960-903710CD47B7\": {\n        \"name\": \"Victoria Peak\"\n    },\n    \"024891DE-B7F6-4187-BFE0-E6D237702EF0\": {\n        \"name\": \"Wan Chai\"\n    },\n    \"64EA30BD-C4B5-4CDD-86D7-DFE47E9CB9AA\": {\n        \"name\": \"Victoria Harbour 2\"\n    },\n    \"E99FA658-A59A-4A2D-9F3B-58E7BDC71A9A\": {\n        \"name\": \"Victoria Harbour\"\n    },\n    \"001C94AE-2BA4-4E77-A202-F7DE60E8B1C8\": {\n        \"name\": \"Liwa Oasis 1\"\n    },\n    \"AFA22C08-A486-4CE8-9A13-E355B6C38559\": {\n        \"name\": \"Liwa Oasis 2\"\n    },\n    \"58754319-8709-4AB0-8674-B34F04E7FFE2\": {\n        \"name\": \"Rio Tamisa\"\n    },\n    \"A5AAFF5D-8887-42BB-8AFD-867EF557ED85\": {\n        \"name\": \"Palácio de Buckingham\"\n    },\n    \"F604AF56-EA77-4960-AEF7-82533CC1A8B3\": {\n        \"name\": \"Rio Tamisa ao pôr do sol\"\n    },\n    \"7F4C26C2-67C2-4C3A-8F07-8A7BF6148C97\": {\n        \"name\": \"Rio Tamisa ao Anoitecer\"\n    },\n    \"CE279831-1CA7-4A83-A97B-FF1E20234396\": {\n        \"name\": \"Aeroporto Internacional de Los Angeles\"\n    },\n    \"35693AEA-F8C4-4A80-B77D-C94B20A68956\": {\n        \"name\": \"Harbor Freeway (Rota 110)\"\n    },\n    \"92E48DE9-13A1-4172-B560-29B4668A87EE\": {\n        \"name\": \"Praia de Santa Monica\"\n    },\n    \"89B1643B-06DD-4DEC-B1B0-774493B0F7B7\": {\n        \"name\": \"Observatório Griffith\"\n    },\n    \"EC67726A-8212-4C5E-83CF-8412932740D2\": {\n        \"name\": \"Hollywood Hills\"\n    },\n    \"F5804DD6-5963-40DA-9FA0-39C0C6E6DEF9\": {\n        \"name\": \"Centro da cidade\"\n    },\n    \"3BA0CFC7-E460-4B59-A817-B97F9EBB9B89\": {\n        \"name\": \"Central Park\"\n    },\n    \"b1-3\": {\n        \"name\": \"Baixa Manhattan\"\n    },\n    \"840FE8E4-D952-4680-B1A7-AC5BACA2C1F8\": {\n        \"name\": \"Upper East Side\"\n    },\n    \"44166C39-8566-4ECA-BD16-43159429B52F\": {\n        \"name\": \"Sétima Avenida\"\n    },\n    \"640DFB00-FBB9-45DA-9444-9F663859F4BC\": {\n        \"name\": \"Baixa Manhattan\"\n    },\n    \"b8-2\": {\n        \"name\": \"Marin Headlands\"\n    },\n    \"EE533FBD-90AE-419A-AD13-D7A60E2015D6\": {\n        \"name\": \"Marin Headlands com Neblina\"\n    },\n    \"DE851E6D-C2BE-4D9F-AB54-0F9CE994DC51\": {\n        \"name\": \"Baía de SF e Golden Gate Bridge\"\n    },\n    \"b8-3\": {\n        \"name\": \"Alamo Square\"\n    },\n    \"85CE77BF-3413-4A7B-9B0F-732E96229A73\": {\n        \"name\": \"Embarcadero, Market Street\"\n    },\n    \"b4-3\": {\n        \"name\": \"Do Presídio para a Golden Gate\"\n    },\n    \"72B4390D-DF1D-4D51-B179-229BBAEFFF2C\": {\n        \"name\": \"Ponte Golden Gate em SF\"\n    },\n    \"b6-4\": {\n        \"name\": \"Centro da cidade e Coit Tower\"\n    },\n    \"29BDF297-EB43-403A-8719-A78DA11A2948\": {\n        \"name\": \"Fisherman’s Wharf\"\n    },\n    \"b5-3\": {\n        \"name\": \"Embarcadero, Market Street\"\n    },\n    \"3E94AE98-EAF2-4B09-96E3-452F46BC114E\": {\n        \"name\": \"Ponte São Francisco\"\n    },\n    \"b2-4\": {\n        \"name\": \"Centro da cidade e Torre Sutro\"\n    },\n    \"4AD99907-9E76-408D-A7FC-8429FF014201\": {\n        \"name\": \"Baía e Embarcadero\"\n    },\n    \"03EC0F5E-CCA8-4E0A-9FEC-5BD1CE151182\": {\n        \"name\": \"Antartica\"\n    },\n    \"737E9E24-49BE-4104-9B72-F352DE1AD2BF\": {\n        \"name\": \"Aurora Borealis (América do Norte)\"\n    },\n    \"A837FA8C-C643-4705-AE92-074EFDD067F7\": {\n        \"name\": \"África a noite\"\n    },\n    \"2F72BC1E-3D76-456C-81EB-842EBA488C27\": {\n        \"name\": \"África e o Oriente Médio\"\n    },\n    \"12318CCB-3F78-43B7-A854-EFDCCE5312CD\": {\n        \"name\": \"Da Califórnia para Vegas\"\n    },\n    \"D5CFB2FF-5F8C-4637-816B-3E42FC1229B8\": {\n        \"name\": \"Caribe\"\n    },\n    \"4F881F8B-A7D9-4FDB-A917-17BF6AC5A589\": {\n        \"name\": \"Caribe de dia\"\n    },\n    \"7825C73A-658F-48EE-B14C-EC56673094AC\": {\n        \"name\": \"China\"\n    },\n    \"E5DB138A-F04E-4619-B896-DE5CB538C534\": {\n        \"name\": \"Da Itália para a Ásia\"\n    },\n    \"F439B0A7-D18C-4B14-9681-6520E6A74FE9\": {\n        \"name\": \"Irã e Afeganistão\"\n    },\n    \"7C643A39-C0B2-4BA0-8BC2-2EAA47CC580E\": {\n        \"name\": \"Da Irlanda para a Ásia\"\n    },\n    \"63C042F0-90EF-4A95-B7CC-CC9A64BF8421\": {\n        \"name\": \"Da África Ocidental para os Alpes\"\n    },\n    \"78911B7E-3C69-47AD-B635-9C2486F6301D\": {\n        \"name\": \"Nova Zelândia\"\n    },\n    \"E556BBC5-D0A0-4DB1-AC77-BC76E4A526F4\": {\n        \"name\": \"Deserto do Saara e Itália\"\n    },\n    \"64D11DAB-3B57-4F14-AD2F-E59A9282FA44\": {\n        \"name\": \"Do Oceano Atlântico à Espanha e França\"\n    },\n    \"81337355-E156-4242-AAF4-711768D30A54\": {\n        \"name\": \"Austrália\"\n    },\n    \"1088217C-1410-4CF7-BDE9-8F573A4DBCD9\": {\n        \"name\": \"Do Caribe para a América Central\"\n    },\n    \"3C4678E4-4D3D-4A40-8817-77752AEA62EB\": {\n        \"name\": \"Delta do Nilo\"\n    },\n    \"87060EC2-D006-4102-98CC-3005C68BB343\": {\n        \"name\": \"Da África do Sul para o Norte da Ásia\"\n    },\n    \"F07CC61B-30FC-4614-BDAD-3240B61F6793\": {\n        \"name\": \"Corais em Palau\"\n    },\n    \"6143116D-03BB-485E-864E-A8CF58ACF6F1\": {\n        \"name\": \"Algas na África do Sul\"\n    },\n    \"2B30E324-E4FF-4CC1-BA45-A958C2D2B2EC\": {\n        \"name\": \"Barracudas\"\n    },\n    \"581A4F1A-2B6D-468C-A1BE-6F473F06D10B\": {\n        \"name\": \"Estrelas do mar\"\n    },\n    \"687D03A2-18A5-4181-8E85-38F3A13409B9\": {\n        \"name\": \"Cardume de Peixe Papagaio Cabeçudo\"\n    },\n    \"537A4DAB-83B0-4B66-BCD1-05E5DBB4A268\": {\n        \"name\": \"Cardume de Sargento\"\n    },\n    \"27A37B0F-738D-4644-A7A4-E33E7A6C1175\": {\n        \"name\": \"Golfinhos na Califórnia\"\n    },\n    \"EB3F48E7-D30F-4079-858F-1A61331D5026\": {\n        \"name\": \"Floresta de Algas da Califórnia\"\n    },\n    \"CE9B5D5B-B6E7-47C5-8C04-59BF182E98FB\": {\n        \"name\": \"Golfinhos da Costa Rica\"\n    },\n    \"58C75C62-3290-47B8-849C-56A583173570\": {\n        \"name\": \"Arraias do mar\"\n    },\n    \"3716DD4B-01C0-4F5B-8DD6-DB771EC472FB\": {\n        \"name\": \"Tubarões Cinzento dos Recifes\"\n    },\n    \"DD47D8E1-CB66-4C12-BFEA-2ADB0D8D1E2E\": {\n        \"name\": \"Baleia Jubarte\"\n    },\n    \"82175C1F-153C-4EC8-AE37-2860EA828004\": {\n        \"name\": \"Coral do Mar Vermelho\"\n    },\n    \"391BDF6E-3279-4CE1-9CA5-0F82811452D7\": {\n        \"name\": \"Focas\"\n    },\n    \"BA4ECA11-592F-4727-9221-D2A32A16EB28\": {\n        \"name\": \"Águas-vivas em Palau 1\"\n    },\n    \"E580E5A5-0888-4BE8-A4CA-F74A18A643C3\": {\n        \"name\": \"Águas-vivas em Palau 2\"\n    },\n    \"EC3DC957-D4C2-4732-AACE-7D0C0F390EC8\": {\n        \"name\": \"Águas-vivas em Palau 3\"\n    },\n    \"C7AD3D0A-7EDF-412C-A237-B3C9D27381A1\": {\n        \"name\": \"Águas-vivas no Alasca 1\"\n    },\n    \"C6DC4E54-1130-44F8-AF6F-A551D8E8A181\": {\n        \"name\": \"Águas-vivas no Alasca 2\"\n    },\n    \"149E7795-DBDA-4F5D-B39A-14712F841118\": {\n        \"name\": \"Ondas do Taiti 1\"\n    },\n    \"8C31B06F-91A4-4F7C-93ED-56146D7F48B9\": {\n        \"name\": \"Ondas do Taiti 2\"\n    }\n}"
  },
  {
    "path": "Resources/Community/ru.json",
    "content": "{\n    \"009BA758-7060-4479-8EE8-FB9B40C8FB97\": {\n        \"name\": \"Корея и Япония ночью\"\n    },\n    \"B1B5DDC5-73C8-4920-8133-BACCE38A08DE\": {\n        \"name\": \"Из Мехико в Нью-Йорк\"\n    },\n    \"7719B48A-2005-4011-9280-2F64EEC6FD91\": {\n        \"name\": \"Из Северной Калифорнии в Нижнюю Калифорнию\"\n    },\n    \"B876B645-3955-420E-99DF-60139E451CF3\": {\n        \"name\": \"Национальный парк Улинъюань\"\n    },\n    \"9CCB8297-E9F5-4699-AE1F-890CFBD5E29C\": {\n        \"name\": \"Рисовые террасы Лунцзи\"\n    },\n    \"D5E76230-81A3-4F65-A1BA-51B8CADED625\": {\n        \"name\": \"Национальный парк Улинъюань\"\n    },\n    \"F0236EC5-EE72-4058-A6CE-1F7D2E8253BF\": {\n        \"name\": \"Великая Китайская стена\"\n    },\n    \"22162A9B-DB90-4517-867C-C676BC3E8E95\": {\n        \"name\": \"Великая Китайская стена\"\n    },\n    \"044AD56C-A107-41B2-90CC-E60CCACFBCF5\": {\n        \"name\": \"Великая Китайская стена\"\n    },\n    \"876D51F4-3D78-4221-8AD2-F9E78C0FD9B9\": {\n        \"name\": \"Шоссе шейха Зайеда\"\n    },\n    \"E991AC0C-F272-44D8-88F3-05F44EDFE3AE\": {\n        \"name\": \"Гавань\"\n    },\n    \"00BA71CD-2C54-415A-A68A-8358E677D750\": {\n        \"name\": \"Центр города\"\n    },\n    \"3FFA2A97-7D28-49EA-AA39-5BC9051B2745\": {\n        \"name\": \"Гавань\"\n    },\n    \"9680B8EB-CE2A-4395-AF41-402801F4D6A6\": {\n        \"name\": \"Приближаясь к Бурдж-Халифе\"\n    },\n    \"2F11E857-4F77-4476-8033-4A1E4610AFCC\": {\n        \"name\": \"Шоссе шейха Зайеда\"\n    },\n    \"B8F204CE-6024-49AB-85F9-7CA2F6DCD226\": {\n        \"name\": \"Полуостров Нууссуак\"\n    },\n    \"2F52E34C-39D4-4AB1-9025-8F7141FAA720\": {\n        \"name\": \"Фьорд Илулиссат-Исфьорд\"\n    },\n    \"EE01F02D-1413-436C-AB05-410F224A5B7B\": {\n        \"name\": \"Фьорд Илулиссат-Исфьорд\"\n    },\n    \"499995FA-E51A-4ACE-8DFD-BDF8AFF6C943\": {\n        \"name\": \"Долина Уэйману\"\n    },\n    \"12E0343D-2CD9-48EA-AB57-4D680FB6D0C7\": {\n        \"name\": \"Лаупахоехое\"\n    },\n    \"b2-2\": {\n        \"name\": \"Долина Хонопу\"\n    },\n    \"258A6797-CC13-4C3A-AB35-4F25CA3BF474\": {\n        \"name\": \"Пуу О Уми\"\n    },\n    \"3D729CFC-9000-48D3-A052-C5BD5B7A6842\": {\n        \"name\": \"Побережье Кохалы\"\n    },\n    \"82BD33C9-B6D2-47E7-9C42-AA3B7758921A\": {\n        \"name\": \"Пуу О Уми\"\n    },\n    \"FE8E1F9D-59BA-4207-B626-28E34D810D0A\": {\n        \"name\": \"Бухта Виктория\"\n    },\n    \"C8559883-6F3E-4AF2-8960-903710CD47B7\": {\n        \"name\": \"Пик Виктория\"\n    },\n    \"024891DE-B7F6-4187-BFE0-E6D237702EF0\": {\n        \"name\": \"Ваньчай\"\n    },\n    \"64EA30BD-C4B5-4CDD-86D7-DFE47E9CB9AA\": {\n        \"name\": \"Бухта Виктория\"\n    },\n    \"E99FA658-A59A-4A2D-9F3B-58E7BDC71A9A\": {\n        \"name\": \"Бухта Виктория\"\n    },\n    \"001C94AE-2BA4-4E77-A202-F7DE60E8B1C8\": {\n        \"name\": \"Оазис Лива\"\n    },\n    \"AFA22C08-A486-4CE8-9A13-E355B6C38559\": {\n        \"name\": \"Оазис Лива\"\n    },\n    \"58754319-8709-4AB0-8674-B34F04E7FFE2\": {\n        \"name\": \"Река Темза\"\n    },\n    \"A5AAFF5D-8887-42BB-8AFD-867EF557ED85\": {\n        \"name\": \"Букингемский дворец\"\n    },\n    \"F604AF56-EA77-4960-AEF7-82533CC1A8B3\": {\n        \"name\": \"Закат на Темзе\"\n    },\n    \"7F4C26C2-67C2-4C3A-8F07-8A7BF6148C97\": {\n        \"name\": \"Река Темза в сумерках\"\n    },\n    \"CE279831-1CA7-4A83-A97B-FF1E20234396\": {\n        \"name\": \"Международный аэропорт Лос-Анджелеса\"\n    },\n    \"35693AEA-F8C4-4A80-B77D-C94B20A68956\": {\n        \"name\": \"Автострада Харбор\"\n    },\n    \"92E48DE9-13A1-4172-B560-29B4668A87EE\": {\n        \"name\": \"Пляж Санта-Моника\"\n    },\n    \"89B1643B-06DD-4DEC-B1B0-774493B0F7B7\": {\n        \"name\": \"Обсерватория Гриффита\"\n    },\n    \"EC67726A-8212-4C5E-83CF-8412932740D2\": {\n        \"name\": \"Голливудские холмы\"\n    },\n    \"F5804DD6-5963-40DA-9FA0-39C0C6E6DEF9\": {\n        \"name\": \"Центр города\"\n    },\n    \"3BA0CFC7-E460-4B59-A817-B97F9EBB9B89\": {\n        \"name\": \"Центральный парк\"\n    },\n    \"b1-3\": {\n        \"name\": \"Нижний Манхэттен\"\n    },\n    \"840FE8E4-D952-4680-B1A7-AC5BACA2C1F8\": {\n        \"name\": \"Верхний Ист-Сайд\"\n    },\n    \"44166C39-8566-4ECA-BD16-43159429B52F\": {\n        \"name\": \"Седьмая авеню\"\n    },\n    \"640DFB00-FBB9-45DA-9444-9F663859F4BC\": {\n        \"name\": \"Нижний Манхэттен\"\n    },\n    \"b8-2\": {\n        \"name\": \"Мыс Марин\"\n    },\n    \"EE533FBD-90AE-419A-AD13-D7A60E2015D6\": {\n        \"name\": \"Мыс Марин в тумане\"\n    },\n    \"DE851E6D-C2BE-4D9F-AB54-0F9CE994DC51\": {\n        \"name\": \"Залив и мост Золотые ворота\"\n    },\n    \"b8-3\": {\n        \"name\": \"Сквер Аламо\"\n    },\n    \"85CE77BF-3413-4A7B-9B0F-732E96229A73\": {\n        \"name\": \"Набережная Эмбаркадеро, Маркет-стрит\"\n    },\n    \"b4-3\": {\n        \"name\": \"От Пресидио до моста Золотые Ворота\"\n    },\n    \"72B4390D-DF1D-4D51-B179-229BBAEFFF2C\": {\n        \"name\": \"Мост Золотые Ворота\"\n    },\n    \"b6-4\": {\n        \"name\": \"Центр города и башня Койт\"\n    },\n    \"29BDF297-EB43-403A-8719-A78DA11A2948\": {\n        \"name\": \"Рыбацкая пристань\"\n    },\n    \"b5-3\": {\n        \"name\": \"Набережная Эмбаркадеро, Маркет-стрит\"\n    },\n    \"3E94AE98-EAF2-4B09-96E3-452F46BC114E\": {\n        \"name\": \"Бэй-Бридж\"\n    },\n    \"b2-4\": {\n        \"name\": \"Центр города и башня Сютро\"\n    },\n    \"4AD99907-9E76-408D-A7FC-8429FF014201\": {\n        \"name\": \"Залив и Эмбаркадеро\"\n    },\n    \"03EC0F5E-CCA8-4E0A-9FEC-5BD1CE151182\": {\n        \"name\": \"Антарктида\"\n    },\n    \"737E9E24-49BE-4104-9B72-F352DE1AD2BF\": {\n        \"name\": \"Северная Америка на рассвете\"\n    },\n    \"A837FA8C-C643-4705-AE92-074EFDD067F7\": {\n        \"name\": \"Африка ночью\"\n    },\n    \"2F72BC1E-3D76-456C-81EB-842EBA488C27\": {\n        \"name\": \"Африка и Ближний Восток\"\n    },\n    \"12318CCB-3F78-43B7-A854-EFDCCE5312CD\": {\n        \"name\": \"Из Калифорнии в Вегас\"\n    },\n    \"D5CFB2FF-5F8C-4637-816B-3E42FC1229B8\": {\n        \"name\": \"Карибы\"\n    },\n    \"4F881F8B-A7D9-4FDB-A917-17BF6AC5A589\": {\n        \"name\": \"Карибы днём\"\n    },\n    \"6324F6EB-E0F1-468F-AC2E-A983EBDDD53B\": {\n        \"name\": \"Китай\"\n    },\n    \"E5DB138A-F04E-4619-B896-DE5CB538C534\": {\n        \"name\": \"Из Италии в Азию\"\n    },\n    \"F439B0A7-D18C-4B14-9681-6520E6A74FE9\": {\n        \"name\": \"Иран и Афганистан\"\n    },\n    \"7C643A39-C0B2-4BA0-8BC2-2EAA47CC580E\": {\n        \"name\": \"Из Ирландии в Азию\"\n    },\n    \"63C042F0-90EF-4A95-B7CC-CC9A64BF8421\": {\n        \"name\": \"От Западной Африки до Альп\"\n    },\n    \"78911B7E-3C69-47AD-B635-9C2486F6301D\": {\n        \"name\": \"Новая Зеландия\"\n    },\n    \"E556BBC5-D0A0-4DB1-AC77-BC76E4A526F4\": {\n        \"name\": \"Сахара и Италия\"\n    },\n    \"64D11DAB-3B57-4F14-AD2F-E59A9282FA44\": {\n        \"name\": \"От Атлантического океана к Испании и Франции\"\n    },\n    \"81337355-E156-4242-AAF4-711768D30A54\": {\n        \"name\": \"Австралия\"\n    },\n    \"1088217C-1410-4CF7-BDE9-8F573A4DBCD9\": {\n        \"name\": \"Из Карибского бассейна в Центральную Америку\"\n    },\n    \"3C4678E4-4D3D-4A40-8817-77752AEA62EB\": {\n        \"name\": \"Дельта Нила\"\n    },\n    \"87060EC2-D006-4102-98CC-3005C68BB343\": {\n        \"name\": \"Из Южной Африки в Северную Азию\"\n    },\n    \"F07CC61B-30FC-4614-BDAD-3240B61F6793\": {\n        \"name\": \"Кораллы у берегов Палау\"\n    },\n    \"6143116D-03BB-485E-864E-A8CF58ACF6F1\": {\n        \"name\": \"Южноафриканские водоросли\"\n    },\n    \"2B30E324-E4FF-4CC1-BA45-A958C2D2B2EC\": {\n        \"name\": \"Барракуды\"\n    },\n    \"581A4F1A-2B6D-468C-A1BE-6F473F06D10B\": {\n        \"name\": \"Морские звёзды\"\n    },\n    \"687D03A2-18A5-4181-8E85-38F3A13409B9\": {\n        \"name\": \"Рыбы-попугаи\"\n    },\n    \"537A4DAB-83B0-4B66-BCD1-05E5DBB4A268\": {\n        \"name\": \"Каранксы\"\n    },\n    \"27A37B0F-738D-4644-A7A4-E33E7A6C1175\": {\n        \"name\": \"Калифорнийские дельфины\"\n    },\n    \"EB3F48E7-D30F-4079-858F-1A61331D5026\": {\n        \"name\": \"Калифорнийский лес водорослей\"\n    },\n    \"CE9B5D5B-B6E7-47C5-8C04-59BF182E98FB\": {\n        \"name\": \"Дельфины Коста-Рики\"\n    },\n    \"58C75C62-3290-47B8-849C-56A583173570\": {\n        \"name\": \"Восточноамериканские бычерылы\"\n    },\n    \"3716DD4B-01C0-4F5B-8DD6-DB771EC472FB\": {\n        \"name\": \"Темнопёрые серые акулы\"\n    },\n    \"DD47D8E1-CB66-4C12-BFEA-2ADB0D8D1E2E\": {\n        \"name\": \"Горбатый кит\"\n    },\n    \"82175C1F-153C-4EC8-AE37-2860EA828004\": {\n        \"name\": \"Кораллы Красного моря\"\n    },\n    \"391BDF6E-3279-4CE1-9CA5-0F82811452D7\": {\n        \"name\": \"Тюлени\"\n    },\n    \"BA4ECA11-592F-4727-9221-D2A32A16EB28\": {\n        \"name\": \"Медузы у берегов Палау\"\n    },\n    \"E580E5A5-0888-4BE8-A4CA-F74A18A643C3\": {\n        \"name\": \"Медузы у берегов Палау\"\n    },\n    \"EC3DC957-D4C2-4732-AACE-7D0C0F390EC8\": {\n        \"name\": \"Медузы у берегов Палау\"\n    },\n    \"C7AD3D0A-7EDF-412C-A237-B3C9D27381A1\": {\n        \"name\": \"Медузы Аляски\"\n    },\n    \"C6DC4E54-1130-44F8-AF6F-A551D8E8A181\": {\n        \"name\": \"Медузы Аляски\"\n    },\n    \"149E7795-DBDA-4F5D-B39A-14712F841118\": {\n        \"name\": \"Волны Таити\"\n    },\n    \"8C31B06F-91A4-4F7C-93ED-56146D7F48B9\": {\n        \"name\": \"Волны Таити\"\n    },\n    \"E334A6D2-7145-47C8-9B00-C20DED08B2D5\": {\n        \"name\": \"Река Колорадо\"\n    },\n    \"DD266E1F-5DF2-4CDB-A2EB-26CE35664657\": {\n        \"name\": \"Каньон Бёрнт\"\n    },\n    \"F9F918CD-E15F-4F01-A326-84A44650C5C9\": {\n        \"name\": \"Закат над Большим каньоном\"\n    },\n    \"AE0115AE-C53B-4DB9-B12F-CA4B7B630CC9\": {\n        \"name\": \"Река Колорадо\"\n    },\n    \"8002C4C8-C611-4894-A068-3D3A3C03472A\": {\n        \"name\": \"Река Колорадо\"\n    },\n    \"5C987900-AD53-469C-8210-CABBCCDDFCAE\": {\n        \"name\": \"Куэрнос-дель-Пайне\"\n    },\n    \"B004358B-5A27-42E5-B49E-93FC100B2371\": {\n        \"name\": \"Озеро Норденшельд\"\n    },\n    \"25A6CFB2-3570-4448-B114-244A4E454B7A\": {\n        \"name\": \"Озеро Норденшельд\"\n    },\n    \"E5D58CC2-3C52-4206-9DA2-427DC88B5896\": {\n        \"name\": \"Национальный парк Торрес-дель-Пайне\"\n    },\n    \"E5799A24-1949-4E66-A17B-B5EB05F28C5D\": {\n        \"name\": \"Скала Хаф-Доум\"\n    },\n    \"E487C6EF-B3FB-427B-A2BE-8CBA60F902F0\": {\n        \"name\": \"Йосемитский национальный парк\"\n    },\n    \"E540DEE6-4C40-42C8-9CCC-D4CB0FAD7D7B\": {\n        \"name\": \"Йосемитский национальный парк\"\n    },\n    \"81CA5ACD-E682-4D8B-A948-0F147EB6ED4F\": {\n        \"name\": \"Йосемитский национальный парк\"\n    },\n    \"4109D42A-D717-46A7-A9A2-FE53A82B25C0\": {\n        \"name\": \"Водопад Брайделвейл и гора Эль-Капитан\"\n    },\n    \"DAD82DCE-F3AE-4AEC-8A79-1694D412FC0A\": {\n        \"name\": \"Луга Туолумне\"\n    },\n    \"8D04D70F-738B-441D-8D43-AF46B2BF8062\": {\n        \"name\": \"Гора Крест Маттеса\"\n    },\n    \"DDE50C77-B7CB-4488-9EB1-D1B13BF21FFE\": {\n        \"name\": \"Река Тунгнаау\"\n    },\n    \"E54D5AFE-F362-4D48-A20D-F2C21D2B5330\": {\n        \"name\": \"Река Йёкульгильсквисль\"\n    },\n    \"8ACF5D77-B22C-416F-B12A-72FB35E2834F\": {\n        \"name\": \"Ландманналаугар\"\n    },\n    \"8590D0C5-E344-4FAC-A39A-FD7BC652AEDA\": {\n        \"name\": \"Озеро Лаунгисьоур\"\n    },\n    \"2F17FCCE-6CCA-4AFA-A08A-C50BF9812DA5\": {\n        \"name\": \"Ледник Мирдальсйёкюдль\"\n    },\n    \"F9518D54-04A7-4793-8666-CFC114D73CE5\": {\n        \"name\": \"Каньон Йёкульгил\"\n    },\n    \"3954A7C4-51EC-4ABC-ABA3-6757AC91C7CF\": {\n        \"name\": \"Залив Лох-Мойдарт\"\n    },\n    \"0C747C29-4BF8-43F6-A5CC-2E012E555341\": {\n        \"name\": \"Остров Скай\"\n    },\n    \"E161929C-0819-4BC2-8359-550C081C7D54\": {\n        \"name\": \"Залив Лох-Мойдарт\"\n    }\n}"
  },
  {
    "path": "Resources/Community/sv.json",
    "content": "{\n    \"009BA758-7060-4479-8EE8-FB9B40C8FB97\": {\n        \"name\": \"Koreahalvön och Japan på natten\"\n    },\n    \"B1B5DDC5-73C8-4920-8133-BACCE38A08DE\": {\n        \"name\": \"Mexico City till New York\"\n    },\n    \"7719B48A-2005-4011-9280-2F64EEC6FD91\": {\n        \"name\": \"Norra Kalifornien till Baja\"\n    },\n    \"B876B645-3955-420E-99DF-60139E451CF3\": {\n        \"name\": \"Nationalparken Wulingyuan 2\"\n    },\n    \"9CCB8297-E9F5-4699-AE1F-890CFBD5E29C\": {\n        \"name\": \"Longji-risterasserna\"\n    },\n    \"D5E76230-81A3-4F65-A1BA-51B8CADED625\": {\n        \"name\": \"Nationalparken Wulingyuan 2\"\n    },\n    \"F0236EC5-EE72-4058-A6CE-1F7D2E8253BF\": {\n        \"name\": \"Kinesiska muren 1\"\n    },\n    \"22162A9B-DB90-4517-867C-C676BC3E8E95\": {\n        \"name\": \"Kinesiska muren 2\"\n    },\n    \"044AD56C-A107-41B2-90CC-E60CCACFBCF5\": {\n        \"name\": \"Kinesiska muren 3\"\n    },\n    \"876D51F4-3D78-4221-8AD2-F9E78C0FD9B9\": {\n        \"name\": \"Sheikh Zayed-vägen\"\n    },\n    \"E991AC0C-F272-44D8-88F3-05F44EDFE3AE\": {\n        \"name\": \"Marina 1\"\n    },\n    \"00BA71CD-2C54-415A-A68A-8358E677D750\": {\n        \"name\": \"Centrala stan\"\n    },\n    \"3FFA2A97-7D28-49EA-AA39-5BC9051B2745\": {\n        \"name\": \"Marina 2\"\n    },\n    \"9680B8EB-CE2A-4395-AF41-402801F4D6A6\": {\n        \"name\": \"På väg mot Burj Khalifa\"\n    },\n    \"2F11E857-4F77-4476-8033-4A1E4610AFCC\": {\n        \"name\": \"Sheikh Zayed-vägen\"\n    },\n    \"B8F204CE-6024-49AB-85F9-7CA2F6DCD226\": {\n        \"name\": \"Nuussuaq-halvön\"\n    },\n    \"2F52E34C-39D4-4AB1-9025-8F7141FAA720\": {\n        \"name\": \"Ilulissatfjorden\"\n    },\n    \"EE01F02D-1413-436C-AB05-410F224A5B7B\": {\n        \"name\": \"Ilulissatfjorden\"\n    },\n    \"499995FA-E51A-4ACE-8DFD-BDF8AFF6C943\": {\n        \"name\": \"Waimanu Valley\"\n    },\n    \"12E0343D-2CD9-48EA-AB57-4D680FB6D0C7\": {\n        \"name\": \"Laupāhoehoe Nui\"\n    },\n    \"b2-2\": {\n        \"name\": \"Honopū Valley\"\n    },\n    \"258A6797-CC13-4C3A-AB35-4F25CA3BF474\": {\n        \"name\": \"Pu'u O 'Umi\"\n    },\n    \"3D729CFC-9000-48D3-A052-C5BD5B7A6842\": {\n        \"name\": \"Kohalas kust \"\n    },\n    \"82BD33C9-B6D2-47E7-9C42-AA3B7758921A\": {\n        \"name\": \"Pu'u O 'Umi\"\n    },\n    \"FE8E1F9D-59BA-4207-B626-28E34D810D0A\": {\n        \"name\": \"Victoria Harbour 1\"\n    },\n    \"C8559883-6F3E-4AF2-8960-903710CD47B7\": {\n        \"name\": \"Victoria Peak\"\n    },\n    \"024891DE-B7F6-4187-BFE0-E6D237702EF0\": {\n        \"name\": \"Wan Chai\"\n    },\n    \"64EA30BD-C4B5-4CDD-86D7-DFE47E9CB9AA\": {\n        \"name\": \"Victoria Harbour 2\"\n    },\n    \"E99FA658-A59A-4A2D-9F3B-58E7BDC71A9A\": {\n        \"name\": \"Victoria Harbour\"\n    },\n    \"001C94AE-2BA4-4E77-A202-F7DE60E8B1C8\": {\n        \"name\": \"Liwa-oasen 1\"\n    },\n    \"AFA22C08-A486-4CE8-9A13-E355B6C38559\": {\n        \"name\": \"Liwa-oasen 2\"\n    },\n    \"58754319-8709-4AB0-8674-B34F04E7FFE2\": {\n        \"name\": \"Themsen\"\n    },\n    \"A5AAFF5D-8887-42BB-8AFD-867EF557ED85\": {\n        \"name\": \"Buckingham Palace\"\n    },\n    \"F604AF56-EA77-4960-AEF7-82533CC1A8B3\": {\n        \"name\": \"Themsen vid solnedgången\"\n    },\n    \"7F4C26C2-67C2-4C3A-8F07-8A7BF6148C97\": {\n        \"name\": \"Themsen vid skymningen\"\n    },\n    \"CE279831-1CA7-4A83-A97B-FF1E20234396\": {\n        \"name\": \"Los Angeles Int'l Airport\"\n    },\n    \"35693AEA-F8C4-4A80-B77D-C94B20A68956\": {\n        \"name\": \"Harbor Freeway\"\n    },\n    \"92E48DE9-13A1-4172-B560-29B4668A87EE\": {\n        \"name\": \"Santa Monica Beach\"\n    },\n    \"89B1643B-06DD-4DEC-B1B0-774493B0F7B7\": {\n        \"name\": \"Griffith Observatory\"\n    },\n    \"EC67726A-8212-4C5E-83CF-8412932740D2\": {\n        \"name\": \"Hollywood Hills\"\n    },\n    \"F5804DD6-5963-40DA-9FA0-39C0C6E6DEF9\": {\n        \"name\": \"Centrala stan\"\n    },\n    \"3BA0CFC7-E460-4B59-A817-B97F9EBB9B89\": {\n        \"name\": \"Central Park\"\n    },\n    \"b1-3\": {\n        \"name\": \"Lower Manhattan\"\n    },\n    \"840FE8E4-D952-4680-B1A7-AC5BACA2C1F8\": {\n        \"name\": \"Upper East Side\"\n    },\n    \"44166C39-8566-4ECA-BD16-43159429B52F\": {\n        \"name\": \"7:e avenyn\"\n    },\n    \"640DFB00-FBB9-45DA-9444-9F663859F4BC\": {\n        \"name\": \"Lower Manhattan\"\n    },\n    \"b8-2\": {\n        \"name\": \"Marin Headlands\"\n    },\n    \"EE533FBD-90AE-419A-AD13-D7A60E2015D6\": {\n        \"name\": \"Marin Headlands i dimma\"\n    },\n    \"DE851E6D-C2BE-4D9F-AB54-0F9CE994DC51\": {\n        \"name\": \"Bukten och Golden Gate\"\n    },\n    \"b8-3\": {\n        \"name\": \"Alamo Square\"\n    },\n    \"85CE77BF-3413-4A7B-9B0F-732E96229A73\": {\n        \"name\": \"Embarcadero, Market Street\"\n    },\n    \"b4-3\": {\n        \"name\": \"Presidio till Golden Gate\"\n    },\n    \"72B4390D-DF1D-4D51-B179-229BBAEFFF2C\": {\n        \"name\": \"Golden Gate från SF\"\n    },\n    \"b6-4\": {\n        \"name\": \"Centrala stan och Coit Tower\"\n    },\n    \"29BDF297-EB43-403A-8719-A78DA11A2948\": {\n        \"name\": \"Fisherman's Wharf\"\n    },\n    \"b5-3\": {\n        \"name\": \"Embarcadero, Market Street\"\n    },\n    \"3E94AE98-EAF2-4B09-96E3-452F46BC114E\": {\n        \"name\": \"Bay Bridge\"\n    },\n    \"b2-4\": {\n        \"name\": \"Centrala stan och Sutro Tower\"\n    },\n    \"4AD99907-9E76-408D-A7FC-8429FF014201\": {\n        \"name\": \"Bukten och Embarcadero\"\n    },\n    \"03EC0F5E-CCA8-4E0A-9FEC-5BD1CE151182\": {\n        \"name\": \"Antarktis\"\n    },\n    \"737E9E24-49BE-4104-9B72-F352DE1AD2BF\": {\n        \"name\": \"Polarsken över Nordamerika\"\n    },\n    \"A837FA8C-C643-4705-AE92-074EFDD067F7\": {\n        \"name\": \"Afrika på natten\"\n    },\n    \"2F72BC1E-3D76-456C-81EB-842EBA488C27\": {\n        \"name\": \"Afrika och Mellanöstern\"\n    },\n    \"12318CCB-3F78-43B7-A854-EFDCCE5312CD\": {\n        \"name\": \"Kalifornien till Vegas\"\n    },\n    \"D5CFB2FF-5F8C-4637-816B-3E42FC1229B8\": {\n        \"name\": \"Karibien\"\n    },\n    \"4F881F8B-A7D9-4FDB-A917-17BF6AC5A589\": {\n        \"name\": \"Karibien på dagen\"\n    },\n    \"7825C73A-658F-48EE-B14C-EC56673094AC\": {\n        \"name\": \"Kina\"\n    },\n    \"E5DB138A-F04E-4619-B896-DE5CB538C534\": {\n        \"name\": \"Italien till Asien\"\n    },\n    \"F439B0A7-D18C-4B14-9681-6520E6A74FE9\": {\n        \"name\": \"Iran och Afghanistan\"\n    },\n    \"7C643A39-C0B2-4BA0-8BC2-2EAA47CC580E\": {\n        \"name\": \"Irland till Asien\"\n    },\n    \"63C042F0-90EF-4A95-B7CC-CC9A64BF8421\": {\n        \"name\": \"Västafrika till Alperna\"\n    },\n    \"78911B7E-3C69-47AD-B635-9C2486F6301D\": {\n        \"name\": \"Nya Zeeland\"\n    },\n    \"E556BBC5-D0A0-4DB1-AC77-BC76E4A526F4\": {\n        \"name\": \"Sahara och Italien\"\n    },\n    \"64D11DAB-3B57-4F14-AD2F-E59A9282FA44\": {\n        \"name\": \"Atlanten till Spanien och Frankrike\"\n    },\n    \"81337355-E156-4242-AAF4-711768D30A54\": {\n        \"name\": \"Australien\"\n    },\n    \"1088217C-1410-4CF7-BDE9-8F573A4DBCD9\": {\n        \"name\": \"Karibien till Centralamerika\"\n    },\n    \"3C4678E4-4D3D-4A40-8817-77752AEA62EB\": {\n        \"name\": \"Nildeltat\"\n    },\n    \"87060EC2-D006-4102-98CC-3005C68BB343\": {\n        \"name\": \"Sydafrika till Nordasien\"\n    },\n    \"F07CC61B-30FC-4614-BDAD-3240B61F6793\": {\n        \"name\": \"Koraller i Palau\"\n    },\n    \"6143116D-03BB-485E-864E-A8CF58ACF6F1\": {\n        \"name\": \"Sydafrikansk tång\"\n    },\n    \"2B30E324-E4FF-4CC1-BA45-A958C2D2B2EC\": {\n        \"name\": \"Barracudor\"\n    },\n    \"581A4F1A-2B6D-468C-A1BE-6F473F06D10B\": {\n        \"name\": \"Sjöstjärnor\"\n    },\n    \"687D03A2-18A5-4181-8E85-38F3A13409B9\": {\n        \"name\": \"Knölhuvuden\"\n    },\n    \"537A4DAB-83B0-4B66-BCD1-05E5DBB4A268\": {\n        \"name\": \"Makriller\"\n    },\n    \"27A37B0F-738D-4644-A7A4-E33E7A6C1175\": {\n        \"name\": \"Delfiner i Kalifornien\"\n    },\n    \"EB3F48E7-D30F-4079-858F-1A61331D5026\": {\n        \"name\": \"Kelpskog i Kalifornien\"\n    },\n    \"CE9B5D5B-B6E7-47C5-8C04-59BF182E98FB\": {\n        \"name\": \"Delfiner i Costa Rica\"\n    },\n    \"58C75C62-3290-47B8-849C-56A583173570\": {\n        \"name\": \"Rockor\"\n    },\n    \"3716DD4B-01C0-4F5B-8DD6-DB771EC472FB\": {\n        \"name\": \"Gråa rävhajar\"\n    },\n    \"DD47D8E1-CB66-4C12-BFEA-2ADB0D8D1E2E\": {\n        \"name\": \"Knölval\"\n    },\n    \"82175C1F-153C-4EC8-AE37-2860EA828004\": {\n        \"name\": \"Koraller i Röda havet \"\n    },\n    \"391BDF6E-3279-4CE1-9CA5-0F82811452D7\": {\n        \"name\": \"Sälar\"\n    },\n    \"BA4ECA11-592F-4727-9221-D2A32A16EB28\": {\n        \"name\": \"Maneter i Palau 1\"\n    },\n    \"E580E5A5-0888-4BE8-A4CA-F74A18A643C3\": {\n        \"name\": \"Maneter i Palau 2\"\n    },\n    \"EC3DC957-D4C2-4732-AACE-7D0C0F390EC8\": {\n        \"name\": \"Maneter i Palau 3\"\n    },\n    \"C7AD3D0A-7EDF-412C-A237-B3C9D27381A1\": {\n        \"name\": \"Maneter i Alaska 1\"\n    },\n    \"C6DC4E54-1130-44F8-AF6F-A551D8E8A181\": {\n        \"name\": \"Maneter i Alaska 2\"\n    },\n    \"149E7795-DBDA-4F5D-B39A-14712F841118\": {\n        \"name\": \"Vågor i Tahiti 1 \"\n    },\n    \"8C31B06F-91A4-4F7C-93ED-56146D7F48B9\": {\n        \"name\": \"Vågor i Tahiti 2\"\n    }\n}"
  },
  {
    "path": "Resources/Community/tl.json",
    "content": "{\n    \"009BA758-7060-4479-8EE8-FB9B40C8FB97\": {\n        \"name\": \"Korea at Japan sa Gabi\"\n    },\n    \"B1B5DDC5-73C8-4920-8133-BACCE38A08DE\": {\n        \"name\": \"Siyudad ng Mexico patungong New York\"\n    },\n    \"7719B48A-2005-4011-9280-2F64EEC6FD91\": {\n        \"name\": \"Hilagang California patungong Baja\"\n    },\n    \"B876B645-3955-420E-99DF-60139E451CF3\": {\n        \"name\": \"Wulingyuan National Park 1\"\n    },\n    \"9CCB8297-E9F5-4699-AE1F-890CFBD5E29C\": {\n        \"name\": \"Longji Rice Terraces\"\n    },\n    \"D5E76230-81A3-4F65-A1BA-51B8CADED625\": {\n        \"name\": \"Wulingyuan National Park 2\"\n    },\n    \"F0236EC5-EE72-4058-A6CE-1F7D2E8253BF\": {\n        \"name\": \"Great Wall 1\"\n    },\n    \"22162A9B-DB90-4517-867C-C676BC3E8E95\": {\n        \"name\": \"Great Wall 2\"\n    },\n    \"044AD56C-A107-41B2-90CC-E60CCACFBCF5\": {\n        \"name\": \"Great Wall 3\"\n    },\n    \"876D51F4-3D78-4221-8AD2-F9E78C0FD9B9\": {\n        \"name\": \"Sheikh Zayed Road\"\n    },\n    \"E991AC0C-F272-44D8-88F3-05F44EDFE3AE\": {\n        \"name\": \"Marina 1\"\n    },\n    \"00BA71CD-2C54-415A-A68A-8358E677D750\": {\n        \"name\": \"Downtown\"\n    },\n    \"3FFA2A97-7D28-49EA-AA39-5BC9051B2745\": {\n        \"name\": \"Marina 2\"\n    },\n    \"9680B8EB-CE2A-4395-AF41-402801F4D6A6\": {\n        \"name\": \"Papalapit ng Burj Khalifa\"\n    },\n    \"2F11E857-4F77-4476-8033-4A1E4610AFCC\": {\n        \"name\": \"Sheikh Zayed Road\"\n    },\n    \"B8F204CE-6024-49AB-85F9-7CA2F6DCD226\": {\n        \"name\": \"Nuussuaq Peninsula\"\n    },\n    \"2F52E34C-39D4-4AB1-9025-8F7141FAA720\": {\n        \"name\": \"Ilulissat Icefjord\"\n    },\n    \"EE01F02D-1413-436C-AB05-410F224A5B7B\": {\n        \"name\": \"Ilulissat Icefjord\"\n    },\n    \"499995FA-E51A-4ACE-8DFD-BDF8AFF6C943\": {\n        \"name\": \"Lambak ng Waimanu\"\n    },\n    \"12E0343D-2CD9-48EA-AB57-4D680FB6D0C7\": {\n        \"name\": \"Laupāhoehoe Nui\"\n    },\n    \"b2-2\": {\n        \"name\": \"Lambak ng Honopū\"\n    },\n    \"258A6797-CC13-4C3A-AB35-4F25CA3BF474\": {\n        \"name\": \"Pu'u O 'Umi\"\n    },\n    \"3D729CFC-9000-48D3-A052-C5BD5B7A6842\": {\n        \"name\": \"Tabing-Dagat sa Kohala\"\n    },\n    \"82BD33C9-B6D2-47E7-9C42-AA3B7758921A\": {\n        \"name\": \"Pu'u O 'Umi\"\n    },\n    \"FE8E1F9D-59BA-4207-B626-28E34D810D0A\": {\n        \"name\": \"Victoria Harbour 1\"\n    },\n    \"C8559883-6F3E-4AF2-8960-903710CD47B7\": {\n        \"name\": \"Victoria Peak\"\n    },\n    \"024891DE-B7F6-4187-BFE0-E6D237702EF0\": {\n        \"name\": \"Wan Chai\"\n    },\n    \"64EA30BD-C4B5-4CDD-86D7-DFE47E9CB9AA\": {\n        \"name\": \"Victoria Harbour 2\"\n    },\n    \"E99FA658-A59A-4A2D-9F3B-58E7BDC71A9A\": {\n        \"name\": \"Victoria Harbour\"\n    },\n    \"001C94AE-2BA4-4E77-A202-F7DE60E8B1C8\": {\n        \"name\": \"Liwa Oasis 1\"\n    },\n    \"AFA22C08-A486-4CE8-9A13-E355B6C38559\": {\n        \"name\": \"Liwa Oasis 2\"\n    },\n    \"58754319-8709-4AB0-8674-B34F04E7FFE2\": {\n        \"name\": \"Ilog Thames\"\n    },\n    \"A5AAFF5D-8887-42BB-8AFD-867EF557ED85\": {\n        \"name\": \"Buckingham Palace\"\n    },\n    \"F604AF56-EA77-4960-AEF7-82533CC1A8B3\": {\n        \"name\": \"Ilog Thames sa Paglubog ng Araw\"\n    },\n    \"7F4C26C2-67C2-4C3A-8F07-8A7BF6148C97\": {\n        \"name\": \"Ilog Thames sa Takipsilim\"\n    },\n    \"CE279831-1CA7-4A83-A97B-FF1E20234396\": {\n        \"name\": \"Los Angeles Int'l Airport\"\n    },\n    \"35693AEA-F8C4-4A80-B77D-C94B20A68956\": {\n        \"name\": \"Harbor Freeway\"\n    },\n    \"92E48DE9-13A1-4172-B560-29B4668A87EE\": {\n        \"name\": \"Santa Monica Beach\"\n    },\n    \"89B1643B-06DD-4DEC-B1B0-774493B0F7B7\": {\n        \"name\": \"Griffith Observatory\"\n    },\n    \"EC67726A-8212-4C5E-83CF-8412932740D2\": {\n        \"name\": \"Hollywood Hills\"\n    },\n    \"F5804DD6-5963-40DA-9FA0-39C0C6E6DEF9\": {\n        \"name\": \"Downtown\"\n    },\n    \"3BA0CFC7-E460-4B59-A817-B97F9EBB9B89\": {\n        \"name\": \"Central Park\"\n    },\n    \"b1-3\": {\n        \"name\": \"Lower Manhattan\"\n    },\n    \"840FE8E4-D952-4680-B1A7-AC5BACA2C1F8\": {\n        \"name\": \"Upper East Side\"\n    },\n    \"44166C39-8566-4ECA-BD16-43159429B52F\": {\n        \"name\": \"Seventh Avenue\"\n    },\n    \"640DFB00-FBB9-45DA-9444-9F663859F4BC\": {\n        \"name\": \"Lower Manhattan\"\n    },\n    \"b8-2\": {\n        \"name\": \"Marin Headlands\"\n    },\n    \"EE533FBD-90AE-419A-AD13-D7A60E2015D6\": {\n        \"name\": \"Marin Headlands sa Ilalim ng Hamog\"\n    },\n    \"DE851E6D-C2BE-4D9F-AB54-0F9CE994DC51\": {\n        \"name\": \"Bay at Golden Gate\"\n    },\n    \"b8-3\": {\n        \"name\": \"Alamo Square\"\n    },\n    \"85CE77BF-3413-4A7B-9B0F-732E96229A73\": {\n        \"name\": \"Embarcadero, Market Street\"\n    },\n    \"b4-3\": {\n        \"name\": \"Presidio patungong Golden Gate\"\n    },\n    \"72B4390D-DF1D-4D51-B179-229BBAEFFF2C\": {\n        \"name\": \"Golden Gate mula SF\"\n    },\n    \"b6-4\": {\n        \"name\": \"Downtown at Coit Tower\"\n    },\n    \"29BDF297-EB43-403A-8719-A78DA11A2948\": {\n        \"name\": \"Fisherman's Wharf\"\n    },\n    \"b5-3\": {\n        \"name\": \"Embarcadero, Market Street\"\n    },\n    \"3E94AE98-EAF2-4B09-96E3-452F46BC114E\": {\n        \"name\": \"Bay Bridge\"\n    },\n    \"b2-4\": {\n        \"name\": \"Downtown at Sutro Tower\"\n    },\n    \"4AD99907-9E76-408D-A7FC-8429FF014201\": {\n        \"name\": \"Bay at Embarcadero\"\n    },\n    \"03EC0F5E-CCA8-4E0A-9FEC-5BD1CE151182\": {\n        \"name\": \"Antartica\"\n    },\n    \"737E9E24-49BE-4104-9B72-F352DE1AD2BF\": {\n        \"name\": \"Aurora sa Hilagang Amerika\"\n    },\n    \"A837FA8C-C643-4705-AE92-074EFDD067F7\": {\n        \"name\": \"Aprika sa Gabi\"\n    },\n    \"2F72BC1E-3D76-456C-81EB-842EBA488C27\": {\n        \"name\": \"Aprika at Gitnang Silangan\"\n    },\n    \"12318CCB-3F78-43B7-A854-EFDCCE5312CD\": {\n        \"name\": \"California patungong Vegas\"\n    },\n    \"D5CFB2FF-5F8C-4637-816B-3E42FC1229B8\": {\n        \"name\": \"Caribbean\"\n    },\n    \"4F881F8B-A7D9-4FDB-A917-17BF6AC5A589\": {\n        \"name\": \"Caribbean sa Umaga\"\n    },\n    \"6324F6EB-E0F1-468F-AC2E-A983EBDDD53B\": {\n        \"name\": \"Tsina\"\n    },\n    \"E5DB138A-F04E-4619-B896-DE5CB538C534\": {\n        \"name\": \"Italya patungong Asya\"\n    },\n    \"F439B0A7-D18C-4B14-9681-6520E6A74FE9\": {\n        \"name\": \"Iran at Afghanistan\"\n    },\n    \"7C643A39-C0B2-4BA0-8BC2-2EAA47CC580E\": {\n        \"name\": \"Ireland patungong Asya\"\n    },\n    \"63C042F0-90EF-4A95-B7CC-CC9A64BF8421\": {\n        \"name\": \"Kanlurang Aprika patungo sa Alps\"\n    },\n    \"78911B7E-3C69-47AD-B635-9C2486F6301D\": {\n        \"name\": \"New Zealand\"\n    },\n    \"E556BBC5-D0A0-4DB1-AC77-BC76E4A526F4\": {\n        \"name\": \"Sahara at Italya\"\n    },\n    \"64D11DAB-3B57-4F14-AD2F-E59A9282FA44\": {\n        \"name\": \"Karagatang Atlantiko patungong Espanya at Pransya\"\n    },\n    \"81337355-E156-4242-AAF4-711768D30A54\": {\n        \"name\": \"Australya\"\n    },\n    \"1088217C-1410-4CF7-BDE9-8F573A4DBCD9\": {\n        \"name\": \"Caribbean patungong Central America\"\n    },\n    \"3C4678E4-4D3D-4A40-8817-77752AEA62EB\": {\n        \"name\": \"Nile Delta\"\n    },\n    \"87060EC2-D006-4102-98CC-3005C68BB343\": {\n        \"name\": \"Timog Aprika patungong Hilagang Asya\"\n    },\n    \"F07CC61B-30FC-4614-BDAD-3240B61F6793\": {\n        \"name\": \"Korales ng Palau\"\n    },\n    \"6143116D-03BB-485E-864E-A8CF58ACF6F1\": {\n        \"name\": \"Kelp ng Timog Aprika\"\n    },\n    \"2B30E324-E4FF-4CC1-BA45-A958C2D2B2EC\": {\n        \"name\": \"Barracuda\"\n    },\n    \"581A4F1A-2B6D-468C-A1BE-6F473F06D10B\": {\n        \"name\": \"Mga Sea Star\"\n    },\n    \"687D03A2-18A5-4181-8E85-38F3A13409B9\": {\n        \"name\": \"Mga Bumphead\"\n    },\n    \"537A4DAB-83B0-4B66-BCD1-05E5DBB4A268\": {\n        \"name\": \"Mga Jack\"\n    },\n    \"27A37B0F-738D-4644-A7A4-E33E7A6C1175\": {\n        \"name\": \"Mga Dolphin sa California\"\n    },\n    \"EB3F48E7-D30F-4079-858F-1A61331D5026\": {\n        \"name\": \"Gubat ng Kelp sa California\"\n    },\n    \"CE9B5D5B-B6E7-47C5-8C04-59BF182E98FB\": {\n        \"name\": \"Mga Dolphin sa Costa Rica\"\n    },\n    \"58C75C62-3290-47B8-849C-56A583173570\": {\n        \"name\": \"Mga Cownose Ray\"\n    },\n    \"3716DD4B-01C0-4F5B-8DD6-DB771EC472FB\": {\n        \"name\": \"Mga Gray Reef Shark\"\n    },\n    \"DD47D8E1-CB66-4C12-BFEA-2ADB0D8D1E2E\": {\n        \"name\": \"Humpback Whale\"\n    },\n    \"82175C1F-153C-4EC8-AE37-2860EA828004\": {\n        \"name\": \"Korales ng Red Sea\"\n    },\n    \"391BDF6E-3279-4CE1-9CA5-0F82811452D7\": {\n        \"name\": \"Seals\"\n    },\n    \"BA4ECA11-592F-4727-9221-D2A32A16EB28\": {\n        \"name\": \"Mga Dikya sa Palau 1\"\n    },\n    \"E580E5A5-0888-4BE8-A4CA-F74A18A643C3\": {\n        \"name\": \"Mga Dikya sa Palau 2\"\n    },\n    \"EC3DC957-D4C2-4732-AACE-7D0C0F390EC8\": {\n        \"name\": \"Mga Dikya sa Palau 3\"\n    },\n    \"C7AD3D0A-7EDF-412C-A237-B3C9D27381A1\": {\n        \"name\": \"Mga Dikya sa Alaska 1\"\n    },\n    \"C6DC4E54-1130-44F8-AF6F-A551D8E8A181\": {\n        \"name\": \"Mga Dikya sa Alaska 2\"\n    },\n    \"149E7795-DBDA-4F5D-B39A-14712F841118\": {\n        \"name\": \"Mga Alon sa Tahiti 1\"\n    },\n    \"8C31B06F-91A4-4F7C-93ED-56146D7F48B9\": {\n        \"name\": \"Mga Alon sa Tahiti 2\"\n    },\n    \"E334A6D2-7145-47C8-9B00-C20DED08B2D5\": {\n        \"name\": \"Ilog Colorado 1\"\n    },\n    \"DD266E1F-5DF2-4CDB-A2EB-26CE35664657\": {\n        \"name\": \"Burnt Canyon\"\n    },\n    \"F9F918CD-E15F-4F01-A326-84A44650C5C9\": {\n        \"name\": \"Sunset sa ibabaw ng Grand Canyon\"\n    },\n    \"AE0115AE-C53B-4DB9-B12F-CA4B7B630CC9\": {\n        \"name\": \"Ilog Colorado 2\"\n    },\n    \"8002C4C8-C611-4894-A068-3D3A3C03472A\": {\n        \"name\": \"Ilog Colorado 3\"\n    },\n    \"5C987900-AD53-469C-8210-CABBCCDDFCAE\": {\n        \"name\": \"Cuernos del Paine\"\n    },\n    \"B004358B-5A27-42E5-B49E-93FC100B2371\": {\n        \"name\": \"Lago Nordenskjöld 1\"\n    },\n    \"25A6CFB2-3570-4448-B114-244A4E454B7A\": {\n        \"name\": \"Lago Nordenskjöld 2\"\n    },\n    \"E5D58CC2-3C52-4206-9DA2-427DC88B5896\": {\n        \"name\": \"Torres del Paine\"\n    },\n    \"E5799A24-1949-4E66-A17B-B5EB05F28C5D\": {\n        \"name\": \"Half Dome\"\n    },\n    \"E487C6EF-B3FB-427B-A2BE-8CBA60F902F0\": {\n        \"name\": \"Yosemite Park 1\"\n    },\n    \"E540DEE6-4C40-42C8-9CCC-D4CB0FAD7D7B\": {\n        \"name\": \"Yosemite Park 2\"\n    },\n    \"81CA5ACD-E682-4D8B-A948-0F147EB6ED4F\": {\n        \"name\": \"Yosemite Park 3\"\n    },\n    \"4109D42A-D717-46A7-A9A2-FE53A82B25C0\": {\n        \"name\": \"Bridalveil Fall at El Capitan\"\n    },\n    \"DAD82DCE-F3AE-4AEC-8A79-1694D412FC0A\": {\n        \"name\": \"Tuolumne Meadows\"\n    },\n    \"8D04D70F-738B-441D-8D43-AF46B2BF8062\": {\n        \"name\": \"Matthes Crest\"\n    },\n    \"DDE50C77-B7CB-4488-9EB1-D1B13BF21FFE\": {\n        \"name\": \"Tungnaá\"\n    },\n    \"E54D5AFE-F362-4D48-A20D-F2C21D2B5330\": {\n        \"name\": \"Ilog Jökulgilskvísl\"\n    },\n    \"8ACF5D77-B22C-416F-B12A-72FB35E2834F\": {\n        \"name\": \"Landmannalaugar\"\n    },\n    \"8590D0C5-E344-4FAC-A39A-FD7BC652AEDA\": {\n        \"name\": \"Langisjór\"\n    },\n    \"2F17FCCE-6CCA-4AFA-A08A-C50BF9812DA5\": {\n        \"name\": \"Mýrdalsjökull\"\n    },\n    \"F9518D54-04A7-4793-8666-CFC114D73CE5\": {\n        \"name\": \"Jökulgil\"\n    },\n    \"3954A7C4-51EC-4ABC-ABA3-6757AC91C7CF\": {\n        \"name\": \"Loch Moidart 1\"\n    },\n    \"0C747C29-4BF8-43F6-A5CC-2E012E555341\": {\n        \"name\": \"Isle of Skye\"\n    },\n    \"E161929C-0819-4BC2-8359-550C081C7D54\": {\n        \"name\": \"Loch Moidart 2\"\n    }\n}"
  },
  {
    "path": "Resources/Community/zh_CN.json",
    "content": "{\n    \"009BA758-7060-4479-8EE8-FB9B40C8FB97\": {\n        \"name\": \"韩国和日本的夜晚\"\n    },\n    \"B1B5DDC5-73C8-4920-8133-BACCE38A08DE\": {\n        \"name\": \"墨西哥城到纽约\"\n    },\n    \"7719B48A-2005-4011-9280-2F64EEC6FD91\": {\n        \"name\": \"加利福尼亚北部到巴哈\"\n    },\n    \"B876B645-3955-420E-99DF-60139E451CF3\": {\n        \"name\": \"武陵源国家公园 1\"\n    },\n    \"9CCB8297-E9F5-4699-AE1F-890CFBD5E29C\": {\n        \"name\": \"龙脊梯田\"\n    },\n    \"D5E76230-81A3-4F65-A1BA-51B8CADED625\": {\n        \"name\": \"武陵源国家公园 2\"\n    },\n    \"F0236EC5-EE72-4058-A6CE-1F7D2E8253BF\": {\n        \"name\": \"万里长城 1\"\n    },\n    \"22162A9B-DB90-4517-867C-C676BC3E8E95\": {\n        \"name\": \"万里长城 2\"\n    },\n    \"044AD56C-A107-41B2-90CC-E60CCACFBCF5\": {\n        \"name\": \"万里长城 3\"\n    },\n    \"876D51F4-3D78-4221-8AD2-F9E78C0FD9B9\": {\n        \"name\": \"谢赫扎耶德路\"\n    },\n    \"E991AC0C-F272-44D8-88F3-05F44EDFE3AE\": {\n        \"name\": \"码头 1\"\n    },\n    \"00BA71CD-2C54-415A-A68A-8358E677D750\": {\n        \"name\": \"市区\"\n    },\n    \"3FFA2A97-7D28-49EA-AA39-5BC9051B2745\": {\n        \"name\": \"码头 2\"\n    },\n    \"9680B8EB-CE2A-4395-AF41-402801F4D6A6\": {\n        \"name\": \"靠近哈利法塔\"\n    },\n    \"2F11E857-4F77-4476-8033-4A1E4610AFCC\": {\n        \"name\": \"谢赫扎耶德路\"\n    },\n    \"B8F204CE-6024-49AB-85F9-7CA2F6DCD226\": {\n        \"name\": \"努苏阿克半岛\"\n    },\n    \"2F52E34C-39D4-4AB1-9025-8F7141FAA720\": {\n        \"name\": \"伊卢利萨特冰峡湾\"\n    },\n    \"EE01F02D-1413-436C-AB05-410F224A5B7B\": {\n        \"name\": \"伊卢利萨特冰峡湾\"\n    },\n    \"499995FA-E51A-4ACE-8DFD-BDF8AFF6C943\": {\n        \"name\": \"鸟之河山谷\"\n    },\n    \"12E0343D-2CD9-48EA-AB57-4D680FB6D0C7\": {\n        \"name\": \"熔岩角\"\n    },\n    \"b2-2\": {\n        \"name\": \"海螺谷\"\n    },\n    \"258A6797-CC13-4C3A-AB35-4F25CA3BF474\": {\n        \"name\": \"海之山自然保护区\"\n    },\n    \"3D729CFC-9000-48D3-A052-C5BD5B7A6842\": {\n        \"name\": \"卡哈拉海岸线\"\n    },\n    \"82BD33C9-B6D2-47E7-9C42-AA3B7758921A\": {\n        \"name\": \"海之山自然保护区\"\n    },\n    \"FE8E1F9D-59BA-4207-B626-28E34D810D0A\": {\n        \"name\": \"维多利亚港 1\"\n    },\n    \"C8559883-6F3E-4AF2-8960-903710CD47B7\": {\n        \"name\": \"太平山\"\n    },\n    \"024891DE-B7F6-4187-BFE0-E6D237702EF0\": {\n        \"name\": \"湾仔\"\n    },\n    \"64EA30BD-C4B5-4CDD-86D7-DFE47E9CB9AA\": {\n        \"name\": \"维多利亚港 2\"\n    },\n    \"E99FA658-A59A-4A2D-9F3B-58E7BDC71A9A\": {\n        \"name\": \"维多利亚港\"\n    },\n    \"001C94AE-2BA4-4E77-A202-F7DE60E8B1C8\": {\n        \"name\": \"利瓦绿洲 1\"\n    },\n    \"AFA22C08-A486-4CE8-9A13-E355B6C38559\": {\n        \"name\": \"利瓦绿洲 2\"\n    },\n    \"58754319-8709-4AB0-8674-B34F04E7FFE2\": {\n        \"name\": \"泰晤士河\"\n    },\n    \"A5AAFF5D-8887-42BB-8AFD-867EF557ED85\": {\n        \"name\": \"白金汉宫\"\n    },\n    \"F604AF56-EA77-4960-AEF7-82533CC1A8B3\": {\n        \"name\": \"黄昏时刻的泰晤士河\"\n    },\n    \"7F4C26C2-67C2-4C3A-8F07-8A7BF6148C97\": {\n        \"name\": \"黄昏时的泰晤士河\"\n    },\n    \"CE279831-1CA7-4A83-A97B-FF1E20234396\": {\n        \"name\": \"洛杉矶国际机场\"\n    },\n    \"35693AEA-F8C4-4A80-B77D-C94B20A68956\": {\n        \"name\": \"港口高速公路\"\n    },\n    \"92E48DE9-13A1-4172-B560-29B4668A87EE\": {\n        \"name\": \"圣塔莫尼卡海滩\"\n    },\n    \"89B1643B-06DD-4DEC-B1B0-774493B0F7B7\": {\n        \"name\": \"格里菲斯天文台\"\n    },\n    \"EC67726A-8212-4C5E-83CF-8412932740D2\": {\n        \"name\": \"好莱坞山\"\n    },\n    \"F5804DD6-5963-40DA-9FA0-39C0C6E6DEF9\": {\n        \"name\": \"市区\"\n    },\n    \"3BA0CFC7-E460-4B59-A817-B97F9EBB9B89\": {\n        \"name\": \"中央公园\"\n    },\n    \"b1-3\": {\n        \"name\": \"曼哈顿下城\"\n    },\n    \"840FE8E4-D952-4680-B1A7-AC5BACA2C1F8\": {\n        \"name\": \"上东区\"\n    },\n    \"44166C39-8566-4ECA-BD16-43159429B52F\": {\n        \"name\": \"第七大道\"\n    },\n    \"640DFB00-FBB9-45DA-9444-9F663859F4BC\": {\n        \"name\": \"曼哈顿下城\"\n    },\n    \"b8-2\": {\n        \"name\": \"马林海岬\"\n    },\n    \"EE533FBD-90AE-419A-AD13-D7A60E2015D6\": {\n        \"name\": \"迷雾中的马林海岬\"\n    },\n    \"DE851E6D-C2BE-4D9F-AB54-0F9CE994DC51\": {\n        \"name\": \"海湾和金门\"\n    },\n    \"b8-3\": {\n        \"name\": \"阿拉莫广场\"\n    },\n    \"85CE77BF-3413-4A7B-9B0F-732E96229A73\": {\n        \"name\": \"市场街的内河码头\"\n    },\n    \"b4-3\": {\n        \"name\": \"要塞到金门\"\n    },\n    \"72B4390D-DF1D-4D51-B179-229BBAEFFF2C\": {\n        \"name\": \"金门\"\n    },\n    \"b6-4\": {\n        \"name\": \"旧金山市区和科伊特塔\"\n    },\n    \"29BDF297-EB43-403A-8719-A78DA11A2948\": {\n        \"name\": \"渔人码头\"\n    },\n    \"b5-3\": {\n        \"name\": \"市场街的内河码头\"\n    },\n    \"3E94AE98-EAF2-4B09-96E3-452F46BC114E\": {\n        \"name\": \"海湾大桥\"\n    },\n    \"b2-4\": {\n        \"name\": \"旧金山市区和苏特罗塔\"\n    },\n    \"4AD99907-9E76-408D-A7FC-8429FF014201\": {\n        \"name\": \"海湾和内河码头\"\n    },\n    \"03EC0F5E-CCA8-4E0A-9FEC-5BD1CE151182\": {\n        \"name\": \"南极洲\"\n    },\n    \"737E9E24-49BE-4104-9B72-F352DE1AD2BF\": {\n        \"name\": \"北美极光\"\n    },\n    \"A837FA8C-C643-4705-AE92-074EFDD067F7\": {\n        \"name\": \"非洲之夜\"\n    },\n    \"2F72BC1E-3D76-456C-81EB-842EBA488C27\": {\n        \"name\": \"非洲和中东\"\n    },\n    \"12318CCB-3F78-43B7-A854-EFDCCE5312CD\": {\n        \"name\": \"加利福尼亚到拉斯维加斯\"\n    },\n    \"D5CFB2FF-5F8C-4637-816B-3E42FC1229B8\": {\n        \"name\": \"加勒比\"\n    },\n    \"4F881F8B-A7D9-4FDB-A917-17BF6AC5A589\": {\n        \"name\": \"加勒比日\"\n    },\n    \"7825C73A-658F-48EE-B14C-EC56673094AC\": {\n        \"name\": \"中国\"\n    },\n    \"E5DB138A-F04E-4619-B896-DE5CB538C534\": {\n        \"name\": \"意大利到亚洲\"\n    },\n    \"F439B0A7-D18C-4B14-9681-6520E6A74FE9\": {\n        \"name\": \"伊朗和阿富汗\"\n    },\n    \"7C643A39-C0B2-4BA0-8BC2-2EAA47CC580E\": {\n        \"name\": \"爱尔兰到亚洲\"\n    },\n    \"63C042F0-90EF-4A95-B7CC-CC9A64BF8421\": {\n        \"name\": \"西非到阿尔卑斯山\"\n    },\n    \"78911B7E-3C69-47AD-B635-9C2486F6301D\": {\n        \"name\": \"新西兰\"\n    },\n    \"E556BBC5-D0A0-4DB1-AC77-BC76E4A526F4\": {\n        \"name\": \"撒哈拉和意大利\"\n    },\n    \"64D11DAB-3B57-4F14-AD2F-E59A9282FA44\": {\n        \"name\": \"从大西洋到西班牙和法国\"\n    },\n    \"81337355-E156-4242-AAF4-711768D30A54\": {\n        \"name\": \"澳大利亚\"\n    },\n    \"1088217C-1410-4CF7-BDE9-8F573A4DBCD9\": {\n        \"name\": \"从加勒比到中美洲\"\n    },\n    \"3C4678E4-4D3D-4A40-8817-77752AEA62EB\": {\n        \"name\": \"尼罗河三角洲\"\n    },\n    \"87060EC2-D006-4102-98CC-3005C68BB343\": {\n        \"name\": \"从南非到北亚\"\n    },\n    \"F07CC61B-30FC-4614-BDAD-3240B61F6793\": {\n        \"name\": \"帕劳珊瑚\"\n    },\n    \"6143116D-03BB-485E-864E-A8CF58ACF6F1\": {\n        \"name\": \"南非海藻\"\n    },\n    \"2B30E324-E4FF-4CC1-BA45-A958C2D2B2EC\": {\n        \"name\": \"梭鱼\"\n    },\n    \"581A4F1A-2B6D-468C-A1BE-6F473F06D10B\": {\n        \"name\": \"海星\"\n    },\n    \"687D03A2-18A5-4181-8E85-38F3A13409B9\": {\n        \"name\": \"隆头鹦鹉鱼\"\n    },\n    \"537A4DAB-83B0-4B66-BCD1-05E5DBB4A268\": {\n        \"name\": \"杰克鱼群\"\n    },\n    \"27A37B0F-738D-4644-A7A4-E33E7A6C1175\": {\n        \"name\": \"加州海豚\"\n    },\n    \"EB3F48E7-D30F-4079-858F-1A61331D5026\": {\n        \"name\": \"加州海藻群\"\n    },\n    \"CE9B5D5B-B6E7-47C5-8C04-59BF182E98FB\": {\n        \"name\": \"哥斯达黎加海豚\"\n    },\n    \"58C75C62-3290-47B8-849C-56A583173570\": {\n        \"name\": \"牛鼻魟\"\n    },\n    \"3716DD4B-01C0-4F5B-8DD6-DB771EC472FB\": {\n        \"name\": \"灰礁鲨\"\n    },\n    \"DD47D8E1-CB66-4C12-BFEA-2ADB0D8D1E2E\": {\n        \"name\": \"座头鲸\"\n    },\n    \"82175C1F-153C-4EC8-AE37-2860EA828004\": {\n        \"name\": \"红海珊瑚\"\n    },\n    \"391BDF6E-3279-4CE1-9CA5-0F82811452D7\": {\n        \"name\": \"海豹\"\n    },\n    \"BA4ECA11-592F-4727-9221-D2A32A16EB28\": {\n        \"name\": \"帕劳水母 1\"\n    },\n    \"E580E5A5-0888-4BE8-A4CA-F74A18A643C3\": {\n        \"name\": \"帕劳水母 2\"\n    },\n    \"EC3DC957-D4C2-4732-AACE-7D0C0F390EC8\": {\n        \"name\": \"帕劳水母 3\"\n    },\n    \"C7AD3D0A-7EDF-412C-A237-B3C9D27381A1\": {\n        \"name\": \"阿拉斯加水母 1\"\n    },\n    \"C6DC4E54-1130-44F8-AF6F-A551D8E8A181\": {\n        \"name\": \"阿拉斯加水母 2\"\n    },\n    \"149E7795-DBDA-4F5D-B39A-14712F841118\": {\n        \"name\": \"大溪地海浪 1\"\n    },\n    \"8C31B06F-91A4-4F7C-93ED-56146D7F48B9\": {\n        \"name\": \"大溪地海浪 2\"\n    }\n}"
  },
  {
    "path": "Resources/Community/zh_TW.json",
    "content": "{\n    \"009BA758-7060-4479-8EE8-FB9B40C8FB97\": {\n        \"name\": \"韓國和日本的夜晚\"\n    },\n    \"B1B5DDC5-73C8-4920-8133-BACCE38A08DE\": {\n        \"name\": \"墨西哥城到紐約\"\n    },\n    \"7719B48A-2005-4011-9280-2F64EEC6FD91\": {\n        \"name\": \"加利福尼亞北部到巴哈\"\n    },\n    \"B876B645-3955-420E-99DF-60139E451CF3\": {\n        \"name\": \"武陵源國家公園 1\"\n    },\n    \"9CCB8297-E9F5-4699-AE1F-890CFBD5E29C\": {\n        \"name\": \"龍脊梯田\"\n    },\n    \"D5E76230-81A3-4F65-A1BA-51B8CADED625\": {\n        \"name\": \"武陵源國家公園 2\"\n    },\n    \"F0236EC5-EE72-4058-A6CE-1F7D2E8253BF\": {\n        \"name\": \"長城 1\"\n    },\n    \"22162A9B-DB90-4517-867C-C676BC3E8E95\": {\n        \"name\": \"長城 2\"\n    },\n    \"044AD56C-A107-41B2-90CC-E60CCACFBCF5\": {\n        \"name\": \"長城 3\"\n    },\n    \"876D51F4-3D78-4221-8AD2-F9E78C0FD9B9\": {\n        \"name\": \"謝赫扎耶德路\"\n    },\n    \"E991AC0C-F272-44D8-88F3-05F44EDFE3AE\": {\n        \"name\": \"碼頭 1\"\n    },\n    \"00BA71CD-2C54-415A-A68A-8358E677D750\": {\n        \"name\": \"市中心\"\n    },\n    \"3FFA2A97-7D28-49EA-AA39-5BC9051B2745\": {\n        \"name\": \"碼頭 2\"\n    },\n    \"9680B8EB-CE2A-4395-AF41-402801F4D6A6\": {\n        \"name\": \"接近哈利法塔\"\n    },\n    \"2F11E857-4F77-4476-8033-4A1E4610AFCC\": {\n        \"name\": \"謝赫扎耶德路\"\n    },\n    \"B8F204CE-6024-49AB-85F9-7CA2F6DCD226\": {\n        \"name\": \"怒蘇阿克半島\"\n    },\n    \"2F52E34C-39D4-4AB1-9025-8F7141FAA720\": {\n        \"name\": \"伊盧利薩特冰峽灣\"\n    },\n    \"EE01F02D-1413-436C-AB05-410F224A5B7B\": {\n        \"name\": \"伊盧利薩特冰峽灣\"\n    },\n    \"499995FA-E51A-4ACE-8DFD-BDF8AFF6C943\": {\n        \"name\": \"鳥之河山谷\"\n    },\n    \"12E0343D-2CD9-48EA-AB57-4D680FB6D0C7\": {\n        \"name\": \"熔岩角\"\n    },\n    \"b2-2\": {\n        \"name\": \"海螺谷\"\n    },\n    \"258A6797-CC13-4C3A-AB35-4F25CA3BF474\": {\n        \"name\": \"海之山自然保護區\"\n    },\n    \"3D729CFC-9000-48D3-A052-C5BD5B7A6842\": {\n        \"name\": \"卡哈拉海岸線\"\n    },\n    \"82BD33C9-B6D2-47E7-9C42-AA3B7758921A\": {\n        \"name\": \"海之山自然保護區\"\n    },\n    \"FE8E1F9D-59BA-4207-B626-28E34D810D0A\": {\n        \"name\": \"維多利亞港 1\"\n    },\n    \"C8559883-6F3E-4AF2-8960-903710CD47B7\": {\n        \"name\": \"太平山頂\"\n    },\n    \"024891DE-B7F6-4187-BFE0-E6D237702EF0\": {\n        \"name\": \"灣仔\"\n    },\n    \"64EA30BD-C4B5-4CDD-86D7-DFE47E9CB9AA\": {\n        \"name\": \"維多利亞港 2\"\n    },\n    \"E99FA658-A59A-4A2D-9F3B-58E7BDC71A9A\": {\n        \"name\": \"維多利亞港\"\n    },\n    \"001C94AE-2BA4-4E77-A202-F7DE60E8B1C8\": {\n        \"name\": \"利瓦綠洲 1\"\n    },\n    \"AFA22C08-A486-4CE8-9A13-E355B6C38559\": {\n        \"name\": \"利瓦綠洲 2\"\n    },\n    \"58754319-8709-4AB0-8674-B34F04E7FFE2\": {\n        \"name\": \"泰晤士河\"\n    },\n    \"A5AAFF5D-8887-42BB-8AFD-867EF557ED85\": {\n        \"name\": \"白金漢宮\"\n    },\n    \"F604AF56-EA77-4960-AEF7-82533CC1A8B3\": {\n        \"name\": \"日落時刻的泰晤士河\"\n    },\n    \"7F4C26C2-67C2-4C3A-8F07-8A7BF6148C97\": {\n        \"name\": \"黃昏的泰晤士河\"\n    },\n    \"CE279831-1CA7-4A83-A97B-FF1E20234396\": {\n        \"name\": \"洛杉磯國際機場\"\n    },\n    \"35693AEA-F8C4-4A80-B77D-C94B20A68956\": {\n        \"name\": \"港口高速公路\"\n    },\n    \"92E48DE9-13A1-4172-B560-29B4668A87EE\": {\n        \"name\": \"聖塔莫尼卡海灘\"\n    },\n    \"89B1643B-06DD-4DEC-B1B0-774493B0F7B7\": {\n        \"name\": \"格里菲斯天文台\"\n    },\n    \"EC67726A-8212-4C5E-83CF-8412932740D2\": {\n        \"name\": \"好萊塢山\"\n    },\n    \"F5804DD6-5963-40DA-9FA0-39C0C6E6DEF9\": {\n        \"name\": \"市中心\"\n    },\n    \"3BA0CFC7-E460-4B59-A817-B97F9EBB9B89\": {\n        \"name\": \"中央公園\"\n    },\n    \"b1-3\": {\n        \"name\": \"曼哈頓下城\"\n    },\n    \"840FE8E4-D952-4680-B1A7-AC5BACA2C1F8\": {\n        \"name\": \"上東區\"\n    },\n    \"44166C39-8566-4ECA-BD16-43159429B52F\": {\n        \"name\": \"第七大道\"\n    },\n    \"640DFB00-FBB9-45DA-9444-9F663859F4BC\": {\n        \"name\": \"曼哈頓下城\"\n    },\n    \"b8-2\": {\n        \"name\": \"馬林岬角\"\n    },\n    \"EE533FBD-90AE-419A-AD13-D7A60E2015D6\": {\n        \"name\": \"霧中的馬林岬角\"\n    },\n    \"DE851E6D-C2BE-4D9F-AB54-0F9CE994DC51\": {\n        \"name\": \"海灣和金門\"\n    },\n    \"b8-3\": {\n        \"name\": \"阿拉莫廣場\"\n    },\n    \"85CE77BF-3413-4A7B-9B0F-732E96229A73\": {\n        \"name\": \"市場街的內河碼頭\"\n    },\n    \"b4-3\": {\n        \"name\": \"要塞到金門\"\n    },\n    \"72B4390D-DF1D-4D51-B179-229BBAEFFF2C\": {\n        \"name\": \"金門\"\n    },\n    \"b6-4\": {\n        \"name\": \"市中心和科伊特塔\"\n    },\n    \"29BDF297-EB43-403A-8719-A78DA11A2948\": {\n        \"name\": \"漁人碼頭\"\n    },\n    \"b5-3\": {\n        \"name\": \"市場街的內河碼頭\"\n    },\n    \"3E94AE98-EAF2-4B09-96E3-452F46BC114E\": {\n        \"name\": \"海灣大橋\"\n    },\n    \"b2-4\": {\n        \"name\": \"市中心和蘇特羅塔\"\n    },\n    \"4AD99907-9E76-408D-A7FC-8429FF014201\": {\n        \"name\": \"海灣和內河碼頭\"\n    },\n    \"03EC0F5E-CCA8-4E0A-9FEC-5BD1CE151182\": {\n        \"name\": \"南極洲\"\n    },\n    \"737E9E24-49BE-4104-9B72-F352DE1AD2BF\": {\n        \"name\": \"北美極光\"\n    },\n    \"A837FA8C-C643-4705-AE92-074EFDD067F7\": {\n        \"name\": \"非洲之夜\"\n    },\n    \"2F72BC1E-3D76-456C-81EB-842EBA488C27\": {\n        \"name\": \"非洲和中東\"\n    },\n    \"12318CCB-3F78-43B7-A854-EFDCCE5312CD\": {\n        \"name\": \"加利福尼亞到拉斯維加斯\"\n    },\n    \"D5CFB2FF-5F8C-4637-816B-3E42FC1229B8\": {\n        \"name\": \"加勒比\"\n    },\n    \"4F881F8B-A7D9-4FDB-A917-17BF6AC5A589\": {\n        \"name\": \"加勒比日\"\n    },\n    \"7825C73A-658F-48EE-B14C-EC56673094AC\": {\n        \"name\": \"中國\"\n    },\n    \"E5DB138A-F04E-4619-B896-DE5CB538C534\": {\n        \"name\": \"義大利到亞洲\"\n    },\n    \"F439B0A7-D18C-4B14-9681-6520E6A74FE9\": {\n        \"name\": \"伊朗和阿富汗\"\n    },\n    \"7C643A39-C0B2-4BA0-8BC2-2EAA47CC580E\": {\n        \"name\": \"愛爾蘭到亞洲\"\n    },\n    \"63C042F0-90EF-4A95-B7CC-CC9A64BF8421\": {\n        \"name\": \"西非到阿爾卑斯山\"\n    },\n    \"78911B7E-3C69-47AD-B635-9C2486F6301D\": {\n        \"name\": \"紐西蘭\"\n    },\n    \"E556BBC5-D0A0-4DB1-AC77-BC76E4A526F4\": {\n        \"name\": \"撒哈拉和義大利\"\n    },\n    \"64D11DAB-3B57-4F14-AD2F-E59A9282FA44\": {\n        \"name\": \"從大西洋到西班牙和法國\"\n    },\n    \"81337355-E156-4242-AAF4-711768D30A54\": {\n        \"name\": \"澳大利亞\"\n    },\n    \"1088217C-1410-4CF7-BDE9-8F573A4DBCD9\": {\n        \"name\": \"從加勒比到中美洲\"\n    },\n    \"3C4678E4-4D3D-4A40-8817-77752AEA62EB\": {\n        \"name\": \"尼羅河三角洲\"\n    },\n    \"87060EC2-D006-4102-98CC-3005C68BB343\": {\n        \"name\": \"從南非到北亞\"\n    },\n    \"F07CC61B-30FC-4614-BDAD-3240B61F6793\": {\n        \"name\": \"帕勞珊瑚\"\n    },\n    \"6143116D-03BB-485E-864E-A8CF58ACF6F1\": {\n        \"name\": \"南非海藻\"\n    },\n    \"2B30E324-E4FF-4CC1-BA45-A958C2D2B2EC\": {\n        \"name\": \"梭魚\"\n    },\n    \"581A4F1A-2B6D-468C-A1BE-6F473F06D10B\": {\n        \"name\": \"海星\"\n    },\n    \"687D03A2-18A5-4181-8E85-38F3A13409B9\": {\n        \"name\": \"隆頭鸚鵡魚\"\n    },\n    \"537A4DAB-83B0-4B66-BCD1-05E5DBB4A268\": {\n        \"name\": \"傑克魚群\"\n    },\n    \"27A37B0F-738D-4644-A7A4-E33E7A6C1175\": {\n        \"name\": \"加州海豚\"\n    },\n    \"EB3F48E7-D30F-4079-858F-1A61331D5026\": {\n        \"name\": \"加州海藻群\"\n    },\n    \"CE9B5D5B-B6E7-47C5-8C04-59BF182E98FB\": {\n        \"name\": \"哥斯達黎加海豚\"\n    },\n    \"58C75C62-3290-47B8-849C-56A583173570\": {\n        \"name\": \"牛鼻魟\"\n    },\n    \"3716DD4B-01C0-4F5B-8DD6-DB771EC472FB\": {\n        \"name\": \"灰礁鯊\"\n    },\n    \"DD47D8E1-CB66-4C12-BFEA-2ADB0D8D1E2E\": {\n        \"name\": \"座頭鯨\"\n    },\n    \"82175C1F-153C-4EC8-AE37-2860EA828004\": {\n        \"name\": \"紅海珊瑚\"\n    },\n    \"391BDF6E-3279-4CE1-9CA5-0F82811452D7\": {\n        \"name\": \"海豹\"\n    },\n    \"BA4ECA11-592F-4727-9221-D2A32A16EB28\": {\n        \"name\": \"帛琉水母 1\"\n    },\n    \"E580E5A5-0888-4BE8-A4CA-F74A18A643C3\": {\n        \"name\": \"帛琉水母 2\"\n    },\n    \"EC3DC957-D4C2-4732-AACE-7D0C0F390EC8\": {\n        \"name\": \"帛琉水母 3\"\n    },\n    \"C7AD3D0A-7EDF-412C-A237-B3C9D27381A1\": {\n        \"name\": \"阿拉斯加水母 1\"\n    },\n    \"C6DC4E54-1130-44F8-AF6F-A551D8E8A181\": {\n        \"name\": \"阿拉斯加水母 2\"\n    },\n    \"149E7795-DBDA-4F5D-B39A-14712F841118\": {\n        \"name\": \"大溪地海浪 2\"\n    },\n    \"8C31B06F-91A4-4F7C-93ED-56146D7F48B9\": {\n        \"name\": \"大溪地海浪 2\"\n    }\n}\n"
  },
  {
    "path": "Resources/MainUI/First time setup/CacheSetupViewController.swift",
    "content": "//\n//  CacheSetupViewController.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 12/08/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Cocoa\n\nclass CacheSetupViewController: NSViewController {\n    @IBOutlet var imageView1: NSButton!\n    @IBOutlet var imageView2: NSButton!\n    @IBOutlet var imageView3: NSButton!\n\n    @IBOutlet var choice1: NSButton!\n    @IBOutlet var choice2: NSButton!\n    @IBOutlet var choice3: NSButton!\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n        // Do view setup here.\n        imageView1.setLargeIcon(\"wand.and.stars\")\n        imageView2.setLargeIcon(\"wand.and.rays\")\n        imageView3.setLargeIcon(\"hand.raised\")\n        PrefsCache.enableManagement = true\n        PrefsCache.cachePeriodicity = .weekly\n    }\n\n    @IBAction func radioChange(_ sender: NSButton) {\n        switch sender {\n        case choice1:\n            PrefsCache.enableManagement = true\n            PrefsCache.cachePeriodicity = .weekly\n        case choice2:\n            PrefsCache.enableManagement = true\n            PrefsCache.cachePeriodicity = .never\n        default:\n            PrefsCache.enableManagement = false\n        }\n    }\n\n}\n"
  },
  {
    "path": "Resources/MainUI/First time setup/CacheSetupViewController.xib",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.Cocoa.XIB\" version=\"3.0\" toolsVersion=\"19529\" targetRuntime=\"MacOSX.Cocoa\" propertyAccessControl=\"none\" useAutolayout=\"YES\" customObjectInstantitationMethod=\"direct\">\n    <dependencies>\n        <deployment identifier=\"macosx\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.CocoaPlugin\" version=\"19529\"/>\n        <capability name=\"documents saved in the Xcode 8 format\" minToolsVersion=\"8.0\"/>\n    </dependencies>\n    <objects>\n        <customObject id=\"-2\" userLabel=\"File's Owner\" customClass=\"CacheSetupViewController\" customModule=\"Aerial\" customModuleProvider=\"target\">\n            <connections>\n                <outlet property=\"choice1\" destination=\"XcL-S1-kOB\" id=\"Voq-Js-ymX\"/>\n                <outlet property=\"choice2\" destination=\"1Me-rs-0he\" id=\"7Ax-Sm-735\"/>\n                <outlet property=\"choice3\" destination=\"w2W-ub-vS9\" id=\"QmT-vG-hde\"/>\n                <outlet property=\"imageView1\" destination=\"hMc-pg-oOv\" id=\"HkM-xa-cnQ\"/>\n                <outlet property=\"imageView2\" destination=\"l8t-Tl-qQy\" id=\"qjK-kw-Ddd\"/>\n                <outlet property=\"imageView3\" destination=\"Fpj-oX-yMI\" id=\"Ihe-dX-BYw\"/>\n                <outlet property=\"view\" destination=\"Hz6-mo-xeY\" id=\"0bl-1N-x8E\"/>\n            </connections>\n        </customObject>\n        <customObject id=\"-1\" userLabel=\"First Responder\" customClass=\"FirstResponder\"/>\n        <customObject id=\"-3\" userLabel=\"Application\" customClass=\"NSObject\"/>\n        <customView id=\"Hz6-mo-xeY\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"800\" height=\"600\"/>\n            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n            <subviews>\n                <box boxType=\"custom\" borderType=\"none\" borderWidth=\"0.0\" title=\"Box\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"hsq-fR-kZy\">\n                    <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"800\" height=\"600\"/>\n                    <view key=\"contentView\" id=\"BwA-rS-hk4\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"800\" height=\"600\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <subviews>\n                            <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"xYV-5e-0ED\">\n                                <rect key=\"frame\" x=\"206\" y=\"537\" width=\"389\" height=\"43\"/>\n                                <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"Video Storage &amp; Cache\" id=\"Nib-Bq-x5T\">\n                                    <font key=\"font\" metaFont=\"systemBold\" size=\"36\"/>\n                                    <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                </textFieldCell>\n                            </textField>\n                            <textField verticalHuggingPriority=\"750\" horizontalCompressionResistancePriority=\"250\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"srx-jV-F0B\">\n                                <rect key=\"frame\" x=\"38\" y=\"473\" width=\"724\" height=\"34\"/>\n                                <textFieldCell key=\"cell\" selectable=\"YES\" id=\"cvh-2z-RAA\">\n                                    <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                    <string key=\"title\">Aerial offers several ways to download videos, from automatically managed to completely manual. Pick what suits you best (you can modify this later, no pressure):</string>\n                                    <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                </textFieldCell>\n                            </textField>\n                            <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"XcL-S1-kOB\">\n                                <rect key=\"frame\" x=\"105\" y=\"397.5\" width=\"447\" height=\"22\"/>\n                                <buttonCell key=\"cell\" type=\"radio\" title=\"Manage everything for me and don't use all my disk space!\" bezelStyle=\"regularSquare\" imagePosition=\"left\" alignment=\"left\" controlSize=\"large\" state=\"on\" inset=\"2\" id=\"FGS-cY-RDE\">\n                                    <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                                    <font key=\"font\" metaFont=\"systemSemibold\" size=\"15\"/>\n                                </buttonCell>\n                                <connections>\n                                    <action selector=\"radioChange:\" target=\"-2\" id=\"4aK-HD-ITb\"/>\n                                </connections>\n                            </button>\n                            <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"1Me-rs-0he\">\n                                <rect key=\"frame\" x=\"105\" y=\"279.5\" width=\"400\" height=\"22\"/>\n                                <buttonCell key=\"cell\" type=\"radio\" title=\"Automatically download videos and keep everything\" bezelStyle=\"regularSquare\" imagePosition=\"left\" alignment=\"left\" controlSize=\"large\" inset=\"2\" id=\"ILy-5P-oiN\">\n                                    <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                                    <font key=\"font\" metaFont=\"systemSemibold\" size=\"15\"/>\n                                </buttonCell>\n                                <connections>\n                                    <action selector=\"radioChange:\" target=\"-2\" id=\"D2w-0W-tsT\"/>\n                                </connections>\n                            </button>\n                            <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"w2W-ub-vS9\">\n                                <rect key=\"frame\" x=\"105\" y=\"161.5\" width=\"178\" height=\"22\"/>\n                                <buttonCell key=\"cell\" type=\"radio\" title=\"Let me handle things\" bezelStyle=\"regularSquare\" imagePosition=\"left\" alignment=\"left\" controlSize=\"large\" inset=\"2\" id=\"h0I-qk-88h\">\n                                    <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                                    <font key=\"font\" metaFont=\"systemSemibold\" size=\"15\"/>\n                                </buttonCell>\n                                <connections>\n                                    <action selector=\"radioChange:\" target=\"-2\" id=\"Q7v-gu-Kfq\"/>\n                                </connections>\n                            </button>\n                            <textField verticalHuggingPriority=\"750\" horizontalCompressionResistancePriority=\"250\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"ghM-dG-rUj\">\n                                <rect key=\"frame\" x=\"128\" y=\"357\" width=\"634\" height=\"34\"/>\n                                <textFieldCell key=\"cell\" selectable=\"YES\" id=\"3vz-2r-56Q\">\n                                    <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                    <string key=\"title\">New videos will automatically download as needed. They will be replaced periodically to keep things fresh. If you really like a video, you can favorite it so it's never replaced by another one. </string>\n                                    <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                </textFieldCell>\n                            </textField>\n                            <textField verticalHuggingPriority=\"750\" horizontalCompressionResistancePriority=\"250\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"A4o-so-B26\">\n                                <rect key=\"frame\" x=\"128\" y=\"239\" width=\"634\" height=\"34\"/>\n                                <textFieldCell key=\"cell\" selectable=\"YES\" id=\"Jhl-bS-PXQ\">\n                                    <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                    <string key=\"title\">New videos will automatically download as needed. Nothing gets deleted unless you say so (by hiding a video). You can still set a cache limit to prevent filling up your disk. </string>\n                                    <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                </textFieldCell>\n                            </textField>\n                            <textField verticalHuggingPriority=\"750\" horizontalCompressionResistancePriority=\"250\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"pgs-xX-pMJ\">\n                                <rect key=\"frame\" x=\"128\" y=\"121\" width=\"634\" height=\"34\"/>\n                                <textFieldCell key=\"cell\" selectable=\"YES\" title=\"Select and download the videos you like, and nothing else. Save or remove as many videos as you want. \" id=\"6Oh-N7-gOc\">\n                                    <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                    <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                </textFieldCell>\n                            </textField>\n                            <button translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"hMc-pg-oOv\">\n                                <rect key=\"frame\" x=\"40\" y=\"370\" width=\"48\" height=\"48\"/>\n                                <constraints>\n                                    <constraint firstAttribute=\"width\" constant=\"48\" id=\"U6S-MV-CpC\"/>\n                                    <constraint firstAttribute=\"height\" constant=\"48\" id=\"zZs-zY-Rcj\"/>\n                                </constraints>\n                                <buttonCell key=\"cell\" type=\"square\" bezelStyle=\"shadowlessSquare\" image=\"wand.and.stars\" imagePosition=\"only\" alignment=\"center\" imageScaling=\"proportionallyUpOrDown\" inset=\"2\" id=\"ZjP-qA-nUv\">\n                                    <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                                    <font key=\"font\" metaFont=\"system\"/>\n                                </buttonCell>\n                            </button>\n                            <button translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"l8t-Tl-qQy\">\n                                <rect key=\"frame\" x=\"40\" y=\"250\" width=\"48\" height=\"52\"/>\n                                <constraints>\n                                    <constraint firstAttribute=\"height\" constant=\"48\" id=\"WAc-Ma-CLw\"/>\n                                    <constraint firstAttribute=\"width\" constant=\"48\" id=\"d40-TP-hw8\"/>\n                                </constraints>\n                                <buttonCell key=\"cell\" type=\"square\" bezelStyle=\"shadowlessSquare\" image=\"opticaldiscdrive\" catalog=\"system\" imagePosition=\"only\" alignment=\"center\" imageScaling=\"proportionallyUpOrDown\" inset=\"2\" id=\"uZ3-cn-fBF\">\n                                    <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                                    <font key=\"font\" metaFont=\"system\"/>\n                                </buttonCell>\n                            </button>\n                            <button translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Fpj-oX-yMI\">\n                                <rect key=\"frame\" x=\"40\" y=\"134\" width=\"48\" height=\"48\"/>\n                                <constraints>\n                                    <constraint firstAttribute=\"width\" constant=\"48\" id=\"YEO-cS-jMe\"/>\n                                    <constraint firstAttribute=\"height\" constant=\"48\" id=\"hxm-4h-HcP\"/>\n                                </constraints>\n                                <buttonCell key=\"cell\" type=\"square\" bezelStyle=\"shadowlessSquare\" image=\"hand.raised\" imagePosition=\"only\" alignment=\"center\" imageScaling=\"proportionallyUpOrDown\" inset=\"2\" id=\"CYm-dg-CIQ\">\n                                    <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                                    <font key=\"font\" metaFont=\"system\"/>\n                                </buttonCell>\n                            </button>\n                            <textField verticalHuggingPriority=\"750\" horizontalCompressionResistancePriority=\"250\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"SkW-In-rev\">\n                                <rect key=\"frame\" x=\"58\" y=\"30\" width=\"684\" height=\"34\"/>\n                                <textFieldCell key=\"cell\" selectable=\"YES\" alignment=\"center\" id=\"CBq-Bc-fCd\">\n                                    <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                    <string key=\"title\">You can change this setting, set your cache size limit, and restrict downloads to approved WiFi networks \nat any time in the Cache options</string>\n                                    <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                </textFieldCell>\n                            </textField>\n                        </subviews>\n                        <constraints>\n                            <constraint firstItem=\"XcL-S1-kOB\" firstAttribute=\"top\" secondItem=\"hMc-pg-oOv\" secondAttribute=\"top\" id=\"0s5-sX-NtI\"/>\n                            <constraint firstItem=\"Fpj-oX-yMI\" firstAttribute=\"top\" secondItem=\"l8t-Tl-qQy\" secondAttribute=\"bottom\" constant=\"70\" id=\"10F-qU-yCm\"/>\n                            <constraint firstAttribute=\"trailing\" secondItem=\"A4o-so-B26\" secondAttribute=\"trailing\" constant=\"40\" id=\"1hn-BW-e5j\"/>\n                            <constraint firstItem=\"SkW-In-rev\" firstAttribute=\"centerX\" secondItem=\"BwA-rS-hk4\" secondAttribute=\"centerX\" id=\"1ta-gE-dg9\"/>\n                            <constraint firstItem=\"hMc-pg-oOv\" firstAttribute=\"leading\" secondItem=\"BwA-rS-hk4\" secondAttribute=\"leading\" constant=\"40\" id=\"8Oq-LA-LyW\"/>\n                            <constraint firstItem=\"pgs-xX-pMJ\" firstAttribute=\"top\" secondItem=\"w2W-ub-vS9\" secondAttribute=\"bottom\" constant=\"8\" symbolic=\"YES\" id=\"DI4-ba-XiX\"/>\n                            <constraint firstItem=\"A4o-so-B26\" firstAttribute=\"leading\" secondItem=\"BwA-rS-hk4\" secondAttribute=\"leading\" constant=\"130\" id=\"IyZ-YB-jRr\"/>\n                            <constraint firstItem=\"ghM-dG-rUj\" firstAttribute=\"top\" secondItem=\"XcL-S1-kOB\" secondAttribute=\"bottom\" constant=\"8\" symbolic=\"YES\" id=\"LJh-Yg-N5h\"/>\n                            <constraint firstItem=\"XcL-S1-kOB\" firstAttribute=\"leading\" secondItem=\"hMc-pg-oOv\" secondAttribute=\"trailing\" constant=\"20\" id=\"P8G-ZR-T6W\"/>\n                            <constraint firstItem=\"w2W-ub-vS9\" firstAttribute=\"top\" secondItem=\"Fpj-oX-yMI\" secondAttribute=\"top\" id=\"PGS-h1-Wd4\"/>\n                            <constraint firstItem=\"XcL-S1-kOB\" firstAttribute=\"top\" secondItem=\"srx-jV-F0B\" secondAttribute=\"bottom\" constant=\"55\" id=\"QBp-QA-Gge\"/>\n                            <constraint firstItem=\"srx-jV-F0B\" firstAttribute=\"leading\" secondItem=\"BwA-rS-hk4\" secondAttribute=\"leading\" constant=\"40\" id=\"QpB-mM-gup\"/>\n                            <constraint firstItem=\"l8t-Tl-qQy\" firstAttribute=\"leading\" secondItem=\"BwA-rS-hk4\" secondAttribute=\"leading\" constant=\"40\" id=\"WFj-7u-C5c\"/>\n                            <constraint firstItem=\"Fpj-oX-yMI\" firstAttribute=\"leading\" secondItem=\"BwA-rS-hk4\" secondAttribute=\"leading\" constant=\"40\" id=\"YrV-bK-7q1\"/>\n                            <constraint firstItem=\"xYV-5e-0ED\" firstAttribute=\"centerX\" secondItem=\"BwA-rS-hk4\" secondAttribute=\"centerX\" id=\"bhz-SN-x5U\"/>\n                            <constraint firstItem=\"xYV-5e-0ED\" firstAttribute=\"top\" secondItem=\"BwA-rS-hk4\" secondAttribute=\"top\" constant=\"20\" id=\"coH-JR-xwq\"/>\n                            <constraint firstItem=\"1Me-rs-0he\" firstAttribute=\"leading\" secondItem=\"l8t-Tl-qQy\" secondAttribute=\"trailing\" constant=\"20\" id=\"gvl-kb-2yj\"/>\n                            <constraint firstItem=\"srx-jV-F0B\" firstAttribute=\"top\" secondItem=\"xYV-5e-0ED\" secondAttribute=\"bottom\" constant=\"30\" id=\"hbC-7T-jHA\"/>\n                            <constraint firstItem=\"ghM-dG-rUj\" firstAttribute=\"leading\" secondItem=\"BwA-rS-hk4\" secondAttribute=\"leading\" constant=\"130\" id=\"iIT-KR-g8a\"/>\n                            <constraint firstAttribute=\"trailing\" secondItem=\"ghM-dG-rUj\" secondAttribute=\"trailing\" constant=\"40\" id=\"ioO-V0-9uH\"/>\n                            <constraint firstAttribute=\"trailing\" secondItem=\"pgs-xX-pMJ\" secondAttribute=\"trailing\" constant=\"40\" id=\"kC4-w7-rAV\"/>\n                            <constraint firstItem=\"w2W-ub-vS9\" firstAttribute=\"leading\" secondItem=\"Fpj-oX-yMI\" secondAttribute=\"trailing\" constant=\"20\" id=\"m8Z-xC-ocI\"/>\n                            <constraint firstItem=\"pgs-xX-pMJ\" firstAttribute=\"leading\" secondItem=\"BwA-rS-hk4\" secondAttribute=\"leading\" constant=\"130\" id=\"n0s-ku-M94\"/>\n                            <constraint firstItem=\"A4o-so-B26\" firstAttribute=\"top\" secondItem=\"1Me-rs-0he\" secondAttribute=\"bottom\" constant=\"8\" symbolic=\"YES\" id=\"p1h-Yj-cHi\"/>\n                            <constraint firstAttribute=\"bottom\" secondItem=\"SkW-In-rev\" secondAttribute=\"bottom\" constant=\"30\" id=\"p9m-J3-71M\"/>\n                            <constraint firstItem=\"1Me-rs-0he\" firstAttribute=\"top\" secondItem=\"l8t-Tl-qQy\" secondAttribute=\"top\" id=\"ssf-xZ-PfP\"/>\n                            <constraint firstItem=\"l8t-Tl-qQy\" firstAttribute=\"top\" secondItem=\"hMc-pg-oOv\" secondAttribute=\"bottom\" constant=\"70\" id=\"xVV-if-ueQ\"/>\n                            <constraint firstAttribute=\"trailing\" secondItem=\"srx-jV-F0B\" secondAttribute=\"trailing\" constant=\"40\" id=\"xeY-l1-WBo\"/>\n                        </constraints>\n                    </view>\n                    <color key=\"fillColor\" name=\"windowBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                </box>\n            </subviews>\n            <constraints>\n                <constraint firstAttribute=\"bottom\" secondItem=\"hsq-fR-kZy\" secondAttribute=\"bottom\" id=\"7EG-SV-dEu\"/>\n                <constraint firstItem=\"hsq-fR-kZy\" firstAttribute=\"top\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"top\" id=\"JLz-sn-r5j\"/>\n                <constraint firstItem=\"hsq-fR-kZy\" firstAttribute=\"leading\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"leading\" id=\"aog-Qt-lH9\"/>\n                <constraint firstAttribute=\"trailing\" secondItem=\"hsq-fR-kZy\" secondAttribute=\"trailing\" id=\"bpU-UJ-dJk\"/>\n            </constraints>\n            <point key=\"canvasLocation\" x=\"-169\" y=\"149\"/>\n        </customView>\n    </objects>\n    <resources>\n        <image name=\"hand.raised\" width=\"153\" height=\"164\"/>\n        <image name=\"opticaldiscdrive\" catalog=\"system\" width=\"18\" height=\"13\"/>\n        <image name=\"wand.and.stars\" width=\"149\" height=\"152\"/>\n    </resources>\n</document>\n"
  },
  {
    "path": "Resources/MainUI/First time setup/FirstSetupWindowController.swift",
    "content": "//\n//  FirstSetupWindowController.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 29/07/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Cocoa\n\nenum Actions {\n    case welcome, videoFormat, cache\n}\n\nclass FirstSetupWindowController: NSWindowController, NSWindowDelegate {\n    var welcomeViewItem: NSSplitViewItem?\n    var videoFormatViewItem: NSSplitViewItem?\n    var cacheSetupViewItem: NSSplitViewItem?\n    var timeViewItem: NSSplitViewItem?\n    var recapViewItem: NSSplitViewItem?\n\n    var nextViewItem: NSSplitViewItem?\n\n    lazy var splitVC = NSSplitViewController()\n    var nextVC: NextViewController = {\n        let bundle = Bundle(for: PanelWindowController.self)\n        return NextViewController(nibName: .init(\"NextViewController\"), bundle: bundle)\n    }()\n\n    var currentStep = 0\n\n    override func windowDidLoad() {\n        super.windowDidLoad()\n\n        splitVC.splitView.isVertical = false\n        if splitVC.splitViewItems.count == 2 {\n            splitVC.removeChild(at: 0)\n            splitVC.removeChild(at: 0)\n        }\n        // We always need to specify a bundle manually, auto loading from bundle\n        // does not work for screen savers when compiled as plugins\n        let bundle = Bundle(for: PanelWindowController.self)\n\n        let welcomeVC = WelcomeViewController(nibName: .init(\"WelcomeViewController\"), bundle: bundle)\n        let videoVC = VideoFormatViewController(nibName: .init(\"VideoFormatViewController\"), bundle: bundle)\n        let cacheVC = CacheSetupViewController(nibName: .init(\"CacheSetupViewController\"), bundle: bundle)\n        let timeVC = TimeSetupViewController(nibName: .init(\"TimeSetupViewController\"), bundle: bundle)\n        let recapVC = RecapViewController(nibName: .init(\"RecapViewController\"), bundle: bundle)\n\n        // let nextVC = NextViewController(nibName: .init(\"NextViewController\"), bundle: bundle)\n        nextVC.windowController = self\n\n        welcomeViewItem = NSSplitViewItem(viewController: welcomeVC)\n        videoFormatViewItem = NSSplitViewItem(viewController: videoVC)\n        cacheSetupViewItem = NSSplitViewItem(viewController: cacheVC)\n        timeViewItem = NSSplitViewItem(viewController: timeVC)\n        recapViewItem = NSSplitViewItem(viewController: recapVC)\n\n        nextViewItem = NSSplitViewItem(viewController: nextVC)\n\n        splitVC.addSplitViewItem(welcomeViewItem!)\n        splitVC.addSplitViewItem(nextViewItem!)\n        window?.contentViewController = splitVC\n    }\n\n    func windowWillClose(_ notification: Notification) {\n        PrefsAdvanced.firstTimeSetup = true\n    }\n\n    func nextAction() {\n        currentStep += 1\n        redrawVC()\n    }\n\n    func previousAction() {\n        currentStep -= 1\n        redrawVC()\n    }\n\n    func redrawVC() {\n        splitVC.removeChild(at: 1)\n        splitVC.removeChild(at: 0)\n\n        switch currentStep {\n        case 0:\n            splitVC.addSplitViewItem(welcomeViewItem!)\n            splitVC.addSplitViewItem(nextViewItem!)\n            nextVC.setNoPrev()\n        case 1:\n            splitVC.addSplitViewItem(videoFormatViewItem!)\n            splitVC.addSplitViewItem(nextViewItem!)\n            nextVC.setPrevNext()\n        case 2:\n            splitVC.addSplitViewItem(cacheSetupViewItem!)\n            splitVC.addSplitViewItem(nextViewItem!)\n            nextVC.setPrevNext()\n        case 3:\n            splitVC.addSplitViewItem(timeViewItem!)\n            splitVC.addSplitViewItem(nextViewItem!)\n            nextVC.setPrevNext()\n        case 4:\n            splitVC.addSplitViewItem(recapViewItem!)\n            splitVC.addSplitViewItem(nextViewItem!)\n            nextVC.setClose()\n        default:\n            window?.close()\n            PrefsAdvanced.firstTimeSetup = true\n        }\n    }\n}\n"
  },
  {
    "path": "Resources/MainUI/First time setup/FirstSetupWindowController.xib",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.Cocoa.XIB\" version=\"3.0\" toolsVersion=\"19529\" targetRuntime=\"MacOSX.Cocoa\" propertyAccessControl=\"none\" useAutolayout=\"YES\" customObjectInstantitationMethod=\"direct\">\n    <dependencies>\n        <deployment identifier=\"macosx\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.CocoaPlugin\" version=\"19529\"/>\n        <capability name=\"documents saved in the Xcode 8 format\" minToolsVersion=\"8.0\"/>\n    </dependencies>\n    <objects>\n        <customObject id=\"-2\" userLabel=\"File's Owner\" customClass=\"FirstSetupWindowController\" customModule=\"Aerial\" customModuleProvider=\"target\">\n            <connections>\n                <outlet property=\"window\" destination=\"F0z-JX-Cv5\" id=\"gIp-Ho-8D9\"/>\n            </connections>\n        </customObject>\n        <customObject id=\"-1\" userLabel=\"First Responder\" customClass=\"FirstResponder\"/>\n        <customObject id=\"-3\" userLabel=\"Application\" customClass=\"NSObject\"/>\n        <window title=\"Welcome to Aerial\" allowsToolTipsWhenApplicationIsInactive=\"NO\" autorecalculatesKeyViewLoop=\"NO\" restorable=\"NO\" releasedWhenClosed=\"NO\" visibleAtLaunch=\"NO\" animationBehavior=\"default\" id=\"F0z-JX-Cv5\">\n            <windowStyleMask key=\"styleMask\" titled=\"YES\" closable=\"YES\"/>\n            <rect key=\"contentRect\" x=\"196\" y=\"240\" width=\"664\" height=\"469\"/>\n            <rect key=\"screenRect\" x=\"0.0\" y=\"0.0\" width=\"2560\" height=\"1415\"/>\n            <view key=\"contentView\" id=\"se5-gp-TjO\">\n                <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"664\" height=\"469\"/>\n                <autoresizingMask key=\"autoresizingMask\"/>\n            </view>\n            <connections>\n                <outlet property=\"delegate\" destination=\"-2\" id=\"0bl-1N-AYu\"/>\n            </connections>\n            <point key=\"canvasLocation\" x=\"-76\" y=\"241.5\"/>\n        </window>\n    </objects>\n</document>\n"
  },
  {
    "path": "Resources/MainUI/First time setup/NextViewController.swift",
    "content": "//\n//  NextViewController.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 29/07/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Cocoa\n\nclass NextViewController: NSViewController {\n    var windowController: FirstSetupWindowController?\n\n    @IBOutlet var nextButton: NSButton!\n    @IBOutlet var previousButton: NSButton!\n    override func viewDidLoad() {\n        super.viewDidLoad()\n        // Do view setup here.\n    }\n\n    func setNoPrev() {\n        previousButton.isEnabled = false\n        nextButton.isEnabled = true\n        nextButton.title = \"Next\"\n    }\n\n    func setPrevNext() {\n        previousButton.isEnabled = true\n        nextButton.isEnabled = true\n        nextButton.title = \"Next\"\n    }\n\n    func setClose() {\n        previousButton.isEnabled = true\n        nextButton.isEnabled = true\n        nextButton.title = \"Close\"\n    }\n\n    @IBAction func previousButtonClick(_ sender: Any) {\n        windowController!.previousAction()\n    }\n\n    @IBAction func nextButtonClick(_ sender: Any) {\n        windowController!.nextAction()\n    }\n}\n"
  },
  {
    "path": "Resources/MainUI/First time setup/NextViewController.xib",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.Cocoa.XIB\" version=\"3.0\" toolsVersion=\"17147\" targetRuntime=\"MacOSX.Cocoa\" propertyAccessControl=\"none\" useAutolayout=\"YES\" customObjectInstantitationMethod=\"direct\">\n    <dependencies>\n        <deployment identifier=\"macosx\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.CocoaPlugin\" version=\"17147\"/>\n        <capability name=\"documents saved in the Xcode 8 format\" minToolsVersion=\"8.0\"/>\n    </dependencies>\n    <objects>\n        <customObject id=\"-2\" userLabel=\"File's Owner\" customClass=\"NextViewController\" customModule=\"Aerial\" customModuleProvider=\"target\">\n            <connections>\n                <outlet property=\"nextButton\" destination=\"zUs-7A-vzy\" id=\"Vqs-FR-DkH\"/>\n                <outlet property=\"previousButton\" destination=\"2M9-G4-wjG\" id=\"gHO-uv-6hX\"/>\n                <outlet property=\"view\" destination=\"Hz6-mo-xeY\" id=\"0bl-1N-x8E\"/>\n            </connections>\n        </customObject>\n        <customObject id=\"-1\" userLabel=\"First Responder\" customClass=\"FirstResponder\"/>\n        <customObject id=\"-3\" userLabel=\"Application\" customClass=\"NSObject\"/>\n        <customView id=\"Hz6-mo-xeY\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"800\" height=\"40\"/>\n            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n            <subviews>\n                <stackView distribution=\"fill\" orientation=\"horizontal\" alignment=\"top\" spacing=\"12\" horizontalStackHuggingPriority=\"249.99998474121094\" verticalStackHuggingPriority=\"249.99998474121094\" detachesHiddenViews=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Zp7-qK-00A\">\n                    <rect key=\"frame\" x=\"321\" y=\"6\" width=\"158\" height=\"28\"/>\n                    <subviews>\n                        <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"2M9-G4-wjG\">\n                            <rect key=\"frame\" x=\"-6\" y=\"-6\" width=\"97\" height=\"40\"/>\n                            <buttonCell key=\"cell\" type=\"push\" title=\"Previous\" bezelStyle=\"rounded\" alignment=\"center\" controlSize=\"large\" enabled=\"NO\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"2WC-JX-7q9\">\n                                <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                                <font key=\"font\" metaFont=\"system\"/>\n                                <string key=\"keyEquivalent\" base64-UTF8=\"YES\">\nDQ\n</string>\n                            </buttonCell>\n                            <connections>\n                                <action selector=\"previousButtonClick:\" target=\"-2\" id=\"G1t-TB-mJi\"/>\n                            </connections>\n                        </button>\n                        <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"zUs-7A-vzy\">\n                            <rect key=\"frame\" x=\"91\" y=\"-6\" width=\"73\" height=\"40\"/>\n                            <buttonCell key=\"cell\" type=\"push\" title=\"Next\" bezelStyle=\"rounded\" alignment=\"center\" controlSize=\"large\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"wCa-ti-Bnl\">\n                                <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                                <font key=\"font\" metaFont=\"system\"/>\n                                <string key=\"keyEquivalent\" base64-UTF8=\"YES\">\nDQ\n</string>\n                            </buttonCell>\n                            <connections>\n                                <action selector=\"nextButtonClick:\" target=\"-2\" id=\"fCj-Nm-FZT\"/>\n                            </connections>\n                        </button>\n                    </subviews>\n                    <visibilityPriorities>\n                        <integer value=\"1000\"/>\n                        <integer value=\"1000\"/>\n                    </visibilityPriorities>\n                    <customSpacing>\n                        <real value=\"3.4028234663852886e+38\"/>\n                        <real value=\"3.4028234663852886e+38\"/>\n                    </customSpacing>\n                </stackView>\n            </subviews>\n            <constraints>\n                <constraint firstItem=\"Zp7-qK-00A\" firstAttribute=\"centerX\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"centerX\" id=\"cOl-Mk-Mxr\"/>\n                <constraint firstItem=\"Zp7-qK-00A\" firstAttribute=\"centerY\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"centerY\" id=\"rLx-cH-zYP\"/>\n            </constraints>\n            <point key=\"canvasLocation\" x=\"-168\" y=\"154\"/>\n        </customView>\n    </objects>\n</document>\n"
  },
  {
    "path": "Resources/MainUI/First time setup/RecapViewController.swift",
    "content": "//\n//  RecapViewController.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 12/08/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Cocoa\n\nclass RecapViewController: NSViewController {\n    @IBOutlet var imageDial: NSImageView!\n    @IBOutlet var imageFav: NSImageView!\n    @IBOutlet var imageHide: NSImageView!\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n        // Do view setup here.\n        imageDial.image = Aerial.helper.getSymbol(\"dial\")?.tinting(with: .secondaryLabelColor)\n        imageFav.image = Aerial.helper.getSymbol(\"star\")?.tinting(with: .secondaryLabelColor)\n        imageHide.image = Aerial.helper.getSymbol(\"eye.slash\")?.tinting(with: .secondaryLabelColor)\n    }\n\n    @IBAction func checkFAQ(_ sender: Any) {\n        let workspace = NSWorkspace.shared\n        let url = URL(string: \"https://aerialscreensaver.github.io/faq.html\")!\n        workspace.open(url)\n    }\n\n    @IBAction func checkJoshHal(_ sender: Any) {\n        let workspace = NSWorkspace.shared\n        let url = URL(string: \"https://www.jetsoncreative.com/aerial\")!\n        workspace.open(url)\n    }\n}\n"
  },
  {
    "path": "Resources/MainUI/First time setup/RecapViewController.xib",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.Cocoa.XIB\" version=\"3.0\" toolsVersion=\"19529\" targetRuntime=\"MacOSX.Cocoa\" propertyAccessControl=\"none\" useAutolayout=\"YES\" customObjectInstantitationMethod=\"direct\">\n    <dependencies>\n        <deployment identifier=\"macosx\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.CocoaPlugin\" version=\"19529\"/>\n        <capability name=\"documents saved in the Xcode 8 format\" minToolsVersion=\"8.0\"/>\n    </dependencies>\n    <objects>\n        <customObject id=\"-2\" userLabel=\"File's Owner\" customClass=\"RecapViewController\" customModule=\"Aerial\" customModuleProvider=\"target\">\n            <connections>\n                <outlet property=\"imageDial\" destination=\"c1U-K9-TU3\" id=\"w0L-87-85a\"/>\n                <outlet property=\"imageFav\" destination=\"FE0-j2-Pzu\" id=\"hKF-8T-Fd4\"/>\n                <outlet property=\"imageHide\" destination=\"DDz-TZ-oBe\" id=\"cHF-9w-Ued\"/>\n                <outlet property=\"view\" destination=\"Hz6-mo-xeY\" id=\"0bl-1N-x8E\"/>\n            </connections>\n        </customObject>\n        <customObject id=\"-1\" userLabel=\"First Responder\" customClass=\"FirstResponder\"/>\n        <customObject id=\"-3\" userLabel=\"Application\" customClass=\"NSObject\"/>\n        <customView id=\"Hz6-mo-xeY\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"800\" height=\"600\"/>\n            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n            <subviews>\n                <box boxType=\"custom\" borderType=\"none\" borderWidth=\"0.0\" title=\"Box\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"6oe-Zp-DQn\">\n                    <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"800\" height=\"600\"/>\n                    <view key=\"contentView\" id=\"FNC-l3-JV2\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"800\" height=\"600\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <subviews>\n                            <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"2Jk-A0-3Qs\">\n                                <rect key=\"frame\" x=\"126\" y=\"477\" width=\"636\" height=\"38\"/>\n                                <textFieldCell key=\"cell\" id=\"oVm-P8-xlE\">\n                                    <font key=\"font\" metaFont=\"system\" size=\"15\"/>\n                                    <string key=\"title\">There are more than 100 different videos! You can pick what you want to see in the Now Playing section. You can pick several locations now, or just play everything.</string>\n                                    <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                </textFieldCell>\n                            </textField>\n                            <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Sxo-rP-7e6\">\n                                <rect key=\"frame\" x=\"76\" y=\"537\" width=\"648\" height=\"43\"/>\n                                <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"Thanks for installing Aerial, some tips...\" id=\"L5R-GJ-M5j\">\n                                    <font key=\"font\" metaFont=\"systemBold\" size=\"36\"/>\n                                    <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                </textFieldCell>\n                            </textField>\n                            <imageView horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"c1U-K9-TU3\">\n                                <rect key=\"frame\" x=\"40\" y=\"472\" width=\"48\" height=\"48\"/>\n                                <constraints>\n                                    <constraint firstAttribute=\"width\" constant=\"48\" id=\"BI6-Ca-NPa\"/>\n                                    <constraint firstAttribute=\"height\" constant=\"48\" id=\"XoL-C6-s32\"/>\n                                </constraints>\n                                <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" image=\"dial\" id=\"6uo-Js-kCL\"/>\n                            </imageView>\n                            <imageView horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"FE0-j2-Pzu\">\n                                <rect key=\"frame\" x=\"40\" y=\"394\" width=\"48\" height=\"48\"/>\n                                <constraints>\n                                    <constraint firstAttribute=\"height\" constant=\"48\" id=\"Kz7-oY-E99\"/>\n                                    <constraint firstAttribute=\"width\" constant=\"48\" id=\"Ymc-c9-KDX\"/>\n                                </constraints>\n                                <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" image=\"star\" id=\"WQk-aW-YMN\"/>\n                            </imageView>\n                            <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Hs3-Sq-hk9\">\n                                <rect key=\"frame\" x=\"126\" y=\"399\" width=\"636\" height=\"38\"/>\n                                <textFieldCell key=\"cell\" title=\"Love outer space? We got you! Aerial lets you choose your favorite videos so that these videos play more often.\" id=\"mQv-cf-25R\">\n                                    <font key=\"font\" metaFont=\"system\" size=\"15\"/>\n                                    <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                </textFieldCell>\n                            </textField>\n                            <imageView horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"DDz-TZ-oBe\">\n                                <rect key=\"frame\" x=\"40\" y=\"316\" width=\"48\" height=\"48\"/>\n                                <constraints>\n                                    <constraint firstAttribute=\"height\" constant=\"48\" id=\"FMg-VJ-UQ8\"/>\n                                    <constraint firstAttribute=\"width\" constant=\"48\" id=\"zbI-vv-lYx\"/>\n                                </constraints>\n                                <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" image=\"eye.slash\" id=\"h1b-o0-7vP\"/>\n                            </imageView>\n                            <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Mj3-l6-dr7\">\n                                <rect key=\"frame\" x=\"126\" y=\"321\" width=\"636\" height=\"38\"/>\n                                <textFieldCell key=\"cell\" title=\"Too hot outside and don’t want to see the desert? That’s okay! Aerial lets you hide videos you don’t like! \" id=\"nu0-MS-den\">\n                                    <font key=\"font\" metaFont=\"system\" size=\"15\"/>\n                                    <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                </textFieldCell>\n                            </textField>\n                            <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"xfz-Dg-MZj\">\n                                <rect key=\"frame\" x=\"48\" y=\"168\" width=\"704\" height=\"60\"/>\n                                <textFieldCell key=\"cell\" id=\"ymw-Ut-XBe\">\n                                    <font key=\"font\" metaFont=\"systemSemibold\" size=\"17\"/>\n                                    <string key=\"title\">Aerial also includes videos shot by multiple contributors. Joshua Michaels &amp; Hal Bergman gifted 20 videos to Aerial. If you enjoy these, consider supporting their work by checking out the additional packs they have made especially for Aerial!</string>\n                                    <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                </textFieldCell>\n                            </textField>\n                            <imageView horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"ogO-Fy-XFK\">\n                                <rect key=\"frame\" x=\"160\" y=\"0.0\" width=\"160\" height=\"90\"/>\n                                <constraints>\n                                    <constraint firstAttribute=\"height\" constant=\"90\" id=\"FDz-cd-SR8\"/>\n                                    <constraint firstAttribute=\"width\" constant=\"160\" id=\"wdc-VQ-8NO\"/>\n                                </constraints>\n                                <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" image=\"video_inspire_alabama_montgomery_countryside_00007\" id=\"CMp-Kk-rqd\"/>\n                            </imageView>\n                            <imageView horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"KAl-O1-TRH\">\n                                <rect key=\"frame\" x=\"320\" y=\"0.0\" width=\"160\" height=\"90\"/>\n                                <constraints>\n                                    <constraint firstAttribute=\"width\" constant=\"160\" id=\"IYk-jq-8HM\"/>\n                                    <constraint firstAttribute=\"height\" constant=\"90\" id=\"hR0-gb-wSq\"/>\n                                </constraints>\n                                <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" image=\"video_inspire_california_catalina_00005\" id=\"L7v-f8-arz\"/>\n                            </imageView>\n                            <imageView horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"DYj-Iq-o0X\">\n                                <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"160\" height=\"90\"/>\n                                <constraints>\n                                    <constraint firstAttribute=\"width\" constant=\"160\" id=\"10M-Lo-h0C\"/>\n                                    <constraint firstAttribute=\"height\" constant=\"90\" id=\"Z7a-YQ-Rmg\"/>\n                                </constraints>\n                                <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" image=\"video_inspire_california_big-sur_2020_00001\" id=\"3vh-QH-u2m\"/>\n                            </imageView>\n                            <imageView horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"iZ3-vX-hQ2\">\n                                <rect key=\"frame\" x=\"640\" y=\"0.0\" width=\"160\" height=\"90\"/>\n                                <constraints>\n                                    <constraint firstAttribute=\"height\" constant=\"90\" id=\"3sC-gY-yUL\"/>\n                                    <constraint firstAttribute=\"width\" constant=\"160\" id=\"qhO-ks-LM8\"/>\n                                </constraints>\n                                <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" image=\"video_inspire_california_vineyard_sierra-mar_sunrise_110\" id=\"vM8-X1-ael\"/>\n                            </imageView>\n                            <imageView horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"IQW-cL-eH7\">\n                                <rect key=\"frame\" x=\"480\" y=\"0.0\" width=\"160\" height=\"90\"/>\n                                <constraints>\n                                    <constraint firstAttribute=\"height\" constant=\"90\" id=\"gWL-K9-0lh\"/>\n                                    <constraint firstAttribute=\"width\" constant=\"160\" id=\"xsY-qL-JKc\"/>\n                                </constraints>\n                                <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" image=\"video_inspire_italy_como_cerano-dintelvi_006\" id=\"EbO-Ei-Jj4\"/>\n                            </imageView>\n                            <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"oDG-SG-2xE\">\n                                <rect key=\"frame\" x=\"301\" y=\"114\" width=\"199\" height=\"40\"/>\n                                <buttonCell key=\"cell\" type=\"push\" title=\"Check out their work here\" bezelStyle=\"rounded\" alignment=\"center\" controlSize=\"large\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"wxW-X8-vOa\">\n                                    <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                                    <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                </buttonCell>\n                                <connections>\n                                    <action selector=\"checkJoshHal:\" target=\"-2\" id=\"soS-uz-t3f\"/>\n                                </connections>\n                            </button>\n                            <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"y8k-xe-ydC\">\n                                <rect key=\"frame\" x=\"237\" y=\"247\" width=\"326\" height=\"40\"/>\n                                <buttonCell key=\"cell\" type=\"push\" title=\"Want to know more? Check out our FAQ here!\" bezelStyle=\"rounded\" alignment=\"center\" controlSize=\"large\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"tEX-da-6YE\">\n                                    <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                                    <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                </buttonCell>\n                                <connections>\n                                    <action selector=\"checkFAQ:\" target=\"-2\" id=\"seE-CX-2qs\"/>\n                                </connections>\n                            </button>\n                        </subviews>\n                        <constraints>\n                            <constraint firstItem=\"FE0-j2-Pzu\" firstAttribute=\"top\" secondItem=\"c1U-K9-TU3\" secondAttribute=\"bottom\" constant=\"30\" id=\"1NG-ay-c4o\"/>\n                            <constraint firstItem=\"oDG-SG-2xE\" firstAttribute=\"top\" secondItem=\"xfz-Dg-MZj\" secondAttribute=\"bottom\" constant=\"20\" id=\"1TJ-pj-wVl\"/>\n                            <constraint firstItem=\"Sxo-rP-7e6\" firstAttribute=\"centerX\" secondItem=\"FNC-l3-JV2\" secondAttribute=\"centerX\" id=\"3OS-1v-K1W\"/>\n                            <constraint firstItem=\"iZ3-vX-hQ2\" firstAttribute=\"leading\" secondItem=\"IQW-cL-eH7\" secondAttribute=\"trailing\" id=\"3oF-uK-OXK\"/>\n                            <constraint firstAttribute=\"trailing\" secondItem=\"Mj3-l6-dr7\" secondAttribute=\"trailing\" constant=\"40\" id=\"534-07-LrM\"/>\n                            <constraint firstAttribute=\"bottom\" secondItem=\"IQW-cL-eH7\" secondAttribute=\"bottom\" id=\"5LI-M7-eP0\"/>\n                            <constraint firstItem=\"DDz-TZ-oBe\" firstAttribute=\"leading\" secondItem=\"FNC-l3-JV2\" secondAttribute=\"leading\" constant=\"40\" id=\"8SP-Ic-tqj\"/>\n                            <constraint firstItem=\"ogO-Fy-XFK\" firstAttribute=\"leading\" secondItem=\"DYj-Iq-o0X\" secondAttribute=\"trailing\" id=\"DFJ-X6-2J5\"/>\n                            <constraint firstItem=\"KAl-O1-TRH\" firstAttribute=\"leading\" secondItem=\"ogO-Fy-XFK\" secondAttribute=\"trailing\" id=\"DZ2-Vk-K1H\"/>\n                            <constraint firstItem=\"Mj3-l6-dr7\" firstAttribute=\"leading\" secondItem=\"DDz-TZ-oBe\" secondAttribute=\"trailing\" constant=\"40\" id=\"LPf-HF-hRt\"/>\n                            <constraint firstItem=\"KAl-O1-TRH\" firstAttribute=\"centerX\" secondItem=\"FNC-l3-JV2\" secondAttribute=\"centerX\" id=\"T1K-qX-qqs\"/>\n                            <constraint firstItem=\"xfz-Dg-MZj\" firstAttribute=\"top\" secondItem=\"y8k-xe-ydC\" secondAttribute=\"bottom\" constant=\"25\" id=\"WHF-JZ-VM2\"/>\n                            <constraint firstItem=\"c1U-K9-TU3\" firstAttribute=\"top\" secondItem=\"FNC-l3-JV2\" secondAttribute=\"top\" constant=\"80\" id=\"XPg-kM-pks\"/>\n                            <constraint firstItem=\"2Jk-A0-3Qs\" firstAttribute=\"leading\" secondItem=\"c1U-K9-TU3\" secondAttribute=\"trailing\" constant=\"40\" id=\"YN2-bj-7UH\"/>\n                            <constraint firstAttribute=\"bottom\" secondItem=\"ogO-Fy-XFK\" secondAttribute=\"bottom\" id=\"bU6-CZ-aGm\"/>\n                            <constraint firstItem=\"y8k-xe-ydC\" firstAttribute=\"centerX\" secondItem=\"FNC-l3-JV2\" secondAttribute=\"centerX\" id=\"bvz-Da-kDR\"/>\n                            <constraint firstItem=\"FE0-j2-Pzu\" firstAttribute=\"leading\" secondItem=\"FNC-l3-JV2\" secondAttribute=\"leading\" constant=\"40\" id=\"c27-Nr-3Lr\"/>\n                            <constraint firstItem=\"c1U-K9-TU3\" firstAttribute=\"leading\" secondItem=\"FNC-l3-JV2\" secondAttribute=\"leading\" constant=\"40\" id=\"cd6-1R-4nL\"/>\n                            <constraint firstAttribute=\"bottom\" secondItem=\"KAl-O1-TRH\" secondAttribute=\"bottom\" id=\"dBc-uF-r1J\"/>\n                            <constraint firstAttribute=\"bottom\" secondItem=\"iZ3-vX-hQ2\" secondAttribute=\"bottom\" id=\"e8g-t2-LMv\"/>\n                            <constraint firstItem=\"IQW-cL-eH7\" firstAttribute=\"leading\" secondItem=\"KAl-O1-TRH\" secondAttribute=\"trailing\" id=\"fHL-sc-yDg\"/>\n                            <constraint firstItem=\"oDG-SG-2xE\" firstAttribute=\"centerX\" secondItem=\"FNC-l3-JV2\" secondAttribute=\"centerX\" id=\"hbe-qb-oml\"/>\n                            <constraint firstAttribute=\"trailing\" secondItem=\"xfz-Dg-MZj\" secondAttribute=\"trailing\" constant=\"50\" id=\"kB6-3N-dyB\"/>\n                            <constraint firstItem=\"Sxo-rP-7e6\" firstAttribute=\"top\" secondItem=\"FNC-l3-JV2\" secondAttribute=\"top\" constant=\"20\" id=\"mKo-yl-9oB\"/>\n                            <constraint firstItem=\"DDz-TZ-oBe\" firstAttribute=\"top\" secondItem=\"FE0-j2-Pzu\" secondAttribute=\"bottom\" constant=\"30\" id=\"mhi-UN-my6\"/>\n                            <constraint firstAttribute=\"trailing\" secondItem=\"Hs3-Sq-hk9\" secondAttribute=\"trailing\" constant=\"40\" id=\"ocD-QR-yWO\"/>\n                            <constraint firstItem=\"y8k-xe-ydC\" firstAttribute=\"top\" secondItem=\"Mj3-l6-dr7\" secondAttribute=\"bottom\" constant=\"40\" id=\"pCI-dk-mGL\"/>\n                            <constraint firstItem=\"Hs3-Sq-hk9\" firstAttribute=\"leading\" secondItem=\"FE0-j2-Pzu\" secondAttribute=\"trailing\" constant=\"40\" id=\"pot-Jw-XjM\"/>\n                            <constraint firstItem=\"xfz-Dg-MZj\" firstAttribute=\"leading\" secondItem=\"FNC-l3-JV2\" secondAttribute=\"leading\" constant=\"50\" id=\"qGN-6R-sFX\"/>\n                            <constraint firstAttribute=\"trailing\" secondItem=\"2Jk-A0-3Qs\" secondAttribute=\"trailing\" constant=\"40\" id=\"wy1-RN-zpQ\"/>\n                            <constraint firstItem=\"Hs3-Sq-hk9\" firstAttribute=\"centerY\" secondItem=\"FE0-j2-Pzu\" secondAttribute=\"centerY\" id=\"xDC-nb-BJK\"/>\n                            <constraint firstAttribute=\"bottom\" secondItem=\"DYj-Iq-o0X\" secondAttribute=\"bottom\" id=\"xw6-Sp-obt\"/>\n                            <constraint firstItem=\"Mj3-l6-dr7\" firstAttribute=\"centerY\" secondItem=\"DDz-TZ-oBe\" secondAttribute=\"centerY\" id=\"y67-wq-D9Z\"/>\n                            <constraint firstItem=\"2Jk-A0-3Qs\" firstAttribute=\"centerY\" secondItem=\"c1U-K9-TU3\" secondAttribute=\"centerY\" id=\"zD9-nF-Uge\"/>\n                        </constraints>\n                    </view>\n                    <constraints>\n                        <constraint firstAttribute=\"width\" constant=\"800\" id=\"Agt-VS-6dP\"/>\n                    </constraints>\n                    <color key=\"fillColor\" name=\"windowBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                </box>\n            </subviews>\n            <constraints>\n                <constraint firstAttribute=\"bottom\" secondItem=\"6oe-Zp-DQn\" secondAttribute=\"bottom\" id=\"Ewj-Kg-fym\"/>\n                <constraint firstAttribute=\"trailing\" secondItem=\"6oe-Zp-DQn\" secondAttribute=\"trailing\" id=\"G3c-Ir-d1m\"/>\n                <constraint firstItem=\"6oe-Zp-DQn\" firstAttribute=\"leading\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"leading\" id=\"Kyl-5F-fyr\"/>\n                <constraint firstItem=\"6oe-Zp-DQn\" firstAttribute=\"top\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"top\" id=\"Skw-BR-yzT\"/>\n            </constraints>\n            <point key=\"canvasLocation\" x=\"-111\" y=\"154\"/>\n        </customView>\n    </objects>\n    <resources>\n        <image name=\"dial\" width=\"163\" height=\"152\"/>\n        <image name=\"eye.slash\" width=\"184\" height=\"129\"/>\n        <image name=\"star\" width=\"154\" height=\"166\"/>\n        <image name=\"video_inspire_alabama_montgomery_countryside_00007\" width=\"192\" height=\"108\"/>\n        <image name=\"video_inspire_california_big-sur_2020_00001\" width=\"192\" height=\"108\"/>\n        <image name=\"video_inspire_california_catalina_00005\" width=\"192\" height=\"108\"/>\n        <image name=\"video_inspire_california_vineyard_sierra-mar_sunrise_110\" width=\"192\" height=\"108\"/>\n        <image name=\"video_inspire_italy_como_cerano-dintelvi_006\" width=\"192\" height=\"108\"/>\n    </resources>\n</document>\n"
  },
  {
    "path": "Resources/MainUI/First time setup/TimeSetupViewController.swift",
    "content": "//\n//  TimeSetupViewController.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 12/08/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Cocoa\n\nclass TimeSetupViewController: NSViewController {\n    @IBOutlet var imageSunrise: NSImageView!\n    @IBOutlet var imageDay: NSImageView!\n    @IBOutlet var imageSunset: NSImageView!\n    @IBOutlet var imageNight: NSImageView!\n\n    @IBOutlet var imageLocation: NSImageView!\n    @IBOutlet var imageClock: NSImageView!\n    @IBOutlet var imageXmark: NSImageView!\n\n    @IBOutlet var locationServicesLink: NSButton!\n\n    @IBOutlet var choice1: NSButton!\n    @IBOutlet var choice2: NSButton!\n    @IBOutlet var choice3: NSButton!\n    @IBOutlet var sunriseTime: NSDatePicker!\n\n    @IBOutlet var sunsetTime: NSDatePicker!\n\n    @IBOutlet var locationLabel: NSTextField!\n\n    lazy var timeFormatter: DateFormatter = {\n        let formatter = DateFormatter()\n        formatter.dateFormat = \"HH:mm\"\n        return formatter\n    }()\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n        // Do view setup here.\n        imageSunrise.image = Aerial.helper.getSymbol(\"sunrise\")?.tinting(with: .secondaryLabelColor)\n        imageDay.image = Aerial.helper.getSymbol(\"sun.max\")?.tinting(with: .secondaryLabelColor)\n        imageSunset.image = Aerial.helper.getSymbol(\"sunset\")?.tinting(with: .secondaryLabelColor)\n        imageNight.image = Aerial.helper.getSymbol(\"moon.stars\")?.tinting(with: .secondaryLabelColor)\n\n        imageLocation.image = Aerial.helper.getSymbol(\"mappin.and.ellipse\")?.tinting(with: .secondaryLabelColor)\n        imageClock.image = Aerial.helper.getSymbol(\"clock\")?.tinting(with: .secondaryLabelColor)\n        imageXmark.image = Aerial.helper.getSymbol(\"xmark.circle\")?.tinting(with: .secondaryLabelColor)\n\n        if let dateSunrise = timeFormatter.date(from: PrefsTime.manualSunrise) {\n            sunriseTime.dateValue = dateSunrise\n        }\n        if let dateSunset = timeFormatter.date(from: PrefsTime.manualSunset) {\n            sunsetTime.dateValue = dateSunset\n        }\n\n        if #available(OSX 10.15, *) {\n            locationServicesLink.isHidden = true\n        }\n\n        locationLabel.stringValue = \"\"\n        PrefsTime.timeMode = .disabled\n    }\n\n    @IBAction func choiceChange(_ sender: NSButton) {\n        switch sender {\n        case choice1:\n            PrefsTime.timeMode = .locationService\n            checkLocation()\n        case choice2:\n            PrefsTime.timeMode = .manual\n\n            PrefsTime.manualSunrise = timeFormatter.string(from: sunriseTime.dateValue)\n            PrefsTime.manualSunset = timeFormatter.string(from: sunsetTime.dateValue)\n\n        default:\n            PrefsTime.timeMode = .disabled\n        }\n    }\n\n    func checkLocation() {\n        // Get the location\n        let location = Locations.sharedInstance\n        locationLabel.stringValue = \"Checking your location...\"\n        location.getCoordinates(failure: { (_) in\n            // swiftlint:disable:next line_length\n            Aerial.helper.showInfoAlert(title: \"Could not get your location\", text: \"Make sure you enabled location services on your Mac, and that Aerial (or legacyScreenSaver on macOS 10.15 and later) is allowed to use your location.\", button1: \"OK\", caution: true)\n            self.locationLabel.stringValue = \"Check your Location Services settings on your mac\"\n\n        }, success: { (_) in\n            // let lat = String(format: \"%.2f\", coordinates.latitude)\n            // let lon = String(format: \"%.2f\", coordinates.longitude)\n\n            _ = TimeManagement.sharedInstance.calculateFromCoordinates()\n            let (sunrise, sunset) = TimeManagement.sharedInstance.getSunriseSunsetForMode(.official)\n\n            if let vSunrise = sunrise, let vSunset = sunset {\n                self.locationLabel.stringValue = \"Next Sunrise : \\(self.timeFormatter.string(from: vSunrise)) Next Sunset: \\(self.timeFormatter.string(from: vSunset))\"\n            } else {\n                self.locationLabel.stringValue = \"Cannot calculate sunset and sunrise\"\n            }\n        })\n    }\n\n    @IBAction func locationServicesClick(_ sender: Any) {\n        let workspace = NSWorkspace.shared\n        let url = URL(string: \"https://github.com/JohnCoates/Aerial/blob/master/Documentation/Troubleshooting.md#issues-on-macos-1014-and-earlier\")!\n        workspace.open(url)\n    }\n\n}\n"
  },
  {
    "path": "Resources/MainUI/First time setup/TimeSetupViewController.xib",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.Cocoa.XIB\" version=\"3.0\" toolsVersion=\"19529\" targetRuntime=\"MacOSX.Cocoa\" propertyAccessControl=\"none\" useAutolayout=\"YES\" customObjectInstantitationMethod=\"direct\">\n    <dependencies>\n        <deployment identifier=\"macosx\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.CocoaPlugin\" version=\"19529\"/>\n        <capability name=\"documents saved in the Xcode 8 format\" minToolsVersion=\"8.0\"/>\n    </dependencies>\n    <objects>\n        <customObject id=\"-2\" userLabel=\"File's Owner\" customClass=\"TimeSetupViewController\" customModule=\"Aerial\" customModuleProvider=\"target\">\n            <connections>\n                <outlet property=\"choice1\" destination=\"22t-gd-Abd\" id=\"GOL-et-7K0\"/>\n                <outlet property=\"choice2\" destination=\"3Nc-Pl-qMy\" id=\"uFJ-zc-KvZ\"/>\n                <outlet property=\"choice3\" destination=\"jHI-px-D0M\" id=\"l12-F4-uDM\"/>\n                <outlet property=\"imageClock\" destination=\"bGh-sP-GO3\" id=\"V7M-VN-IxG\"/>\n                <outlet property=\"imageDay\" destination=\"Kg7-RC-BKS\" id=\"ur1-1b-YTT\"/>\n                <outlet property=\"imageLocation\" destination=\"eZG-Mf-Rud\" id=\"7F9-I0-hk6\"/>\n                <outlet property=\"imageNight\" destination=\"T24-un-ptU\" id=\"9EX-Ha-9FT\"/>\n                <outlet property=\"imageSunrise\" destination=\"8Gn-K5-OVb\" id=\"5NB-0U-cpW\"/>\n                <outlet property=\"imageSunset\" destination=\"TcC-uv-cSc\" id=\"clb-uX-vKQ\"/>\n                <outlet property=\"imageXmark\" destination=\"uzu-Lk-YXP\" id=\"75W-Q8-TGB\"/>\n                <outlet property=\"locationLabel\" destination=\"oA4-ui-9wq\" id=\"nfu-Ki-2Ko\"/>\n                <outlet property=\"locationServicesLink\" destination=\"6mZ-LV-nEO\" id=\"iO2-QP-ArA\"/>\n                <outlet property=\"sunriseTime\" destination=\"FMY-kx-tOP\" id=\"ttM-rg-lOi\"/>\n                <outlet property=\"sunsetTime\" destination=\"utR-AS-8Il\" id=\"HEh-Y8-Ybj\"/>\n                <outlet property=\"view\" destination=\"Hz6-mo-xeY\" id=\"0bl-1N-x8E\"/>\n            </connections>\n        </customObject>\n        <customObject id=\"-1\" userLabel=\"First Responder\" customClass=\"FirstResponder\"/>\n        <customObject id=\"-3\" userLabel=\"Application\" customClass=\"NSObject\"/>\n        <customView id=\"Hz6-mo-xeY\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"800\" height=\"600\"/>\n            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n            <subviews>\n                <box boxType=\"custom\" borderType=\"none\" borderWidth=\"0.0\" title=\"Box\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"KeN-Yr-ChJ\">\n                    <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"800\" height=\"600\"/>\n                    <view key=\"contentView\" id=\"Qil-A7-nRJ\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"800\" height=\"600\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <subviews>\n                            <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"U3I-0O-JPu\">\n                                <rect key=\"frame\" x=\"168\" y=\"537\" width=\"465\" height=\"43\"/>\n                                <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"Adapt videos based on time\" id=\"HlA-RS-Oa5\">\n                                    <font key=\"font\" metaFont=\"systemBold\" size=\"36\"/>\n                                    <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                </textFieldCell>\n                            </textField>\n                            <textField verticalHuggingPriority=\"750\" horizontalCompressionResistancePriority=\"250\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"fZE-lx-nSW\">\n                                <rect key=\"frame\" x=\"38\" y=\"456\" width=\"724\" height=\"51\"/>\n                                <textFieldCell key=\"cell\" selectable=\"YES\" id=\"2BM-mL-IKm\">\n                                    <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                    <string key=\"title\">Aerial can use your local time to display a more immersive experience that only shows certain videos during a given time of day. For example, nighttime videos are only shown at night. Your location can be used to precisely calculate your local sunrise and sunset time. Your location isn't shared with anyone.</string>\n                                    <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                </textFieldCell>\n                            </textField>\n                            <stackView distribution=\"fill\" orientation=\"horizontal\" alignment=\"top\" horizontalStackHuggingPriority=\"249.99998474121094\" verticalStackHuggingPriority=\"249.99998474121094\" detachesHiddenViews=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"MX3-T8-nNh\">\n                                <rect key=\"frame\" x=\"292\" y=\"378\" width=\"216\" height=\"48\"/>\n                                <subviews>\n                                    <imageView horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"8Gn-K5-OVb\">\n                                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"48\" height=\"48\"/>\n                                        <constraints>\n                                            <constraint firstAttribute=\"width\" constant=\"48\" id=\"ehk-TK-mKO\"/>\n                                            <constraint firstAttribute=\"height\" constant=\"48\" id=\"qPd-a6-qRE\"/>\n                                        </constraints>\n                                        <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" image=\"sunrise\" id=\"8Yx-rb-eNx\"/>\n                                    </imageView>\n                                    <imageView horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Kg7-RC-BKS\">\n                                        <rect key=\"frame\" x=\"56\" y=\"0.0\" width=\"48\" height=\"48\"/>\n                                        <constraints>\n                                            <constraint firstAttribute=\"height\" constant=\"48\" id=\"5NA-cG-JtC\"/>\n                                            <constraint firstAttribute=\"width\" constant=\"48\" id=\"qaS-Jp-jti\"/>\n                                        </constraints>\n                                        <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" image=\"sun.max\" id=\"jcB-w8-DdZ\"/>\n                                    </imageView>\n                                    <imageView horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"TcC-uv-cSc\">\n                                        <rect key=\"frame\" x=\"112\" y=\"0.0\" width=\"48\" height=\"48\"/>\n                                        <constraints>\n                                            <constraint firstAttribute=\"height\" constant=\"48\" id=\"Iim-hl-uBK\"/>\n                                            <constraint firstAttribute=\"width\" constant=\"48\" id=\"Oh1-5S-oOP\"/>\n                                        </constraints>\n                                        <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" image=\"sunset\" id=\"0dg-bt-afc\"/>\n                                    </imageView>\n                                    <imageView horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"T24-un-ptU\">\n                                        <rect key=\"frame\" x=\"168\" y=\"0.0\" width=\"48\" height=\"48\"/>\n                                        <constraints>\n                                            <constraint firstAttribute=\"width\" constant=\"48\" id=\"7ZK-Uu-feV\"/>\n                                            <constraint firstAttribute=\"height\" constant=\"48\" id=\"hhv-Ti-krv\"/>\n                                        </constraints>\n                                        <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" image=\"moon.stars\" id=\"SME-gf-lY7\"/>\n                                    </imageView>\n                                </subviews>\n                                <visibilityPriorities>\n                                    <integer value=\"1000\"/>\n                                    <integer value=\"1000\"/>\n                                    <integer value=\"1000\"/>\n                                    <integer value=\"1000\"/>\n                                </visibilityPriorities>\n                                <customSpacing>\n                                    <real value=\"3.4028234663852886e+38\"/>\n                                    <real value=\"3.4028234663852886e+38\"/>\n                                    <real value=\"3.4028234663852886e+38\"/>\n                                    <real value=\"3.4028234663852886e+38\"/>\n                                </customSpacing>\n                            </stackView>\n                            <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"22t-gd-Abd\">\n                                <rect key=\"frame\" x=\"125\" y=\"317.5\" width=\"369\" height=\"22\"/>\n                                <buttonCell key=\"cell\" type=\"radio\" title=\"Use my location to calculate sunrise and sunset\" bezelStyle=\"regularSquare\" imagePosition=\"left\" alignment=\"left\" controlSize=\"large\" inset=\"2\" id=\"wah-Hv-bQN\">\n                                    <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                                    <font key=\"font\" metaFont=\"systemSemibold\" size=\"15\"/>\n                                </buttonCell>\n                                <connections>\n                                    <action selector=\"choiceChange:\" target=\"-2\" id=\"ut8-HW-YAu\"/>\n                                </connections>\n                            </button>\n                            <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"jHI-px-D0M\">\n                                <rect key=\"frame\" x=\"125\" y=\"125.5\" width=\"172\" height=\"22\"/>\n                                <buttonCell key=\"cell\" type=\"radio\" title=\"Do not adapt videos\" bezelStyle=\"regularSquare\" imagePosition=\"left\" alignment=\"left\" controlSize=\"large\" state=\"on\" inset=\"2\" id=\"TVP-xh-4qx\">\n                                    <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                                    <font key=\"font\" metaFont=\"systemSemibold\" size=\"15\"/>\n                                </buttonCell>\n                                <connections>\n                                    <action selector=\"choiceChange:\" target=\"-2\" id=\"UeF-Yc-EnJ\"/>\n                                </connections>\n                            </button>\n                            <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"3Nc-Pl-qMy\">\n                                <rect key=\"frame\" x=\"125\" y=\"221.5\" width=\"238\" height=\"22\"/>\n                                <buttonCell key=\"cell\" type=\"radio\" title=\"Use manually specified times\" bezelStyle=\"regularSquare\" imagePosition=\"left\" alignment=\"left\" controlSize=\"large\" inset=\"2\" id=\"FMW-zb-neL\">\n                                    <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                                    <font key=\"font\" metaFont=\"systemSemibold\" size=\"15\"/>\n                                </buttonCell>\n                                <connections>\n                                    <action selector=\"choiceChange:\" target=\"-2\" id=\"y7b-lg-bOM\"/>\n                                </connections>\n                            </button>\n                            <imageView horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"eZG-Mf-Rud\">\n                                <rect key=\"frame\" x=\"40\" y=\"290\" width=\"48\" height=\"48\"/>\n                                <constraints>\n                                    <constraint firstAttribute=\"height\" constant=\"48\" id=\"Q8K-YN-gwP\"/>\n                                    <constraint firstAttribute=\"width\" constant=\"48\" id=\"wjY-4F-ESh\"/>\n                                </constraints>\n                                <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" image=\"mappin.and.ellipse\" id=\"Nd0-z7-SqD\"/>\n                            </imageView>\n                            <imageView horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"bGh-sP-GO3\">\n                                <rect key=\"frame\" x=\"40\" y=\"194\" width=\"48\" height=\"48\"/>\n                                <constraints>\n                                    <constraint firstAttribute=\"height\" constant=\"48\" id=\"l63-uT-F8a\"/>\n                                    <constraint firstAttribute=\"width\" constant=\"48\" id=\"nUJ-Ar-G4P\"/>\n                                </constraints>\n                                <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" image=\"clock\" id=\"AJa-jB-rF7\"/>\n                            </imageView>\n                            <imageView horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"uzu-Lk-YXP\">\n                                <rect key=\"frame\" x=\"40\" y=\"98\" width=\"48\" height=\"48\"/>\n                                <constraints>\n                                    <constraint firstAttribute=\"width\" constant=\"48\" id=\"CCE-NS-WPI\"/>\n                                    <constraint firstAttribute=\"height\" constant=\"48\" id=\"kLn-pH-UYg\"/>\n                                </constraints>\n                                <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" image=\"xmark.circle\" id=\"lGF-hn-GgW\"/>\n                            </imageView>\n                            <textField verticalHuggingPriority=\"750\" horizontalCompressionResistancePriority=\"250\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"l3V-Qj-BKa\">\n                                <rect key=\"frame\" x=\"150\" y=\"294\" width=\"386\" height=\"17\"/>\n                                <textFieldCell key=\"cell\" selectable=\"YES\" title=\"This requires Location Services to be enabled on your Mac.\" id=\"DQp-Vt-8zr\">\n                                    <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                    <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                </textFieldCell>\n                            </textField>\n                            <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"oA4-ui-9wq\">\n                                <rect key=\"frame\" x=\"150\" y=\"262\" width=\"37\" height=\"16\"/>\n                                <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"Label\" id=\"2b8-hX-G9x\">\n                                    <font key=\"font\" usesAppearanceFont=\"YES\"/>\n                                    <color key=\"textColor\" name=\"secondaryLabelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                </textFieldCell>\n                            </textField>\n                            <datePicker verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"utR-AS-8Il\">\n                                <rect key=\"frame\" x=\"389\" y=\"186\" width=\"42\" height=\"21\"/>\n                                <datePickerCell key=\"cell\" controlSize=\"large\" borderStyle=\"bezel\" alignment=\"left\" id=\"ubf-2V-peM\">\n                                    <font key=\"font\" metaFont=\"system\"/>\n                                    <date key=\"date\" timeIntervalSinceReferenceDate=\"618948000.78890002\">\n                                        <!--2020-08-12 18:00:00 +0000-->\n                                    </date>\n                                    <color key=\"backgroundColor\" name=\"controlBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <datePickerElements key=\"datePickerElements\" hour=\"YES\" minute=\"YES\"/>\n                                </datePickerCell>\n                            </datePicker>\n                            <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"8VH-do-LRN\">\n                                <rect key=\"frame\" x=\"150\" y=\"190\" width=\"57\" height=\"17\"/>\n                                <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" title=\"Sunrise:\" id=\"nhn-KG-MPz\">\n                                    <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                    <color key=\"textColor\" name=\"secondaryLabelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                </textFieldCell>\n                            </textField>\n                            <datePicker verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"FMY-kx-tOP\">\n                                <rect key=\"frame\" x=\"213\" y=\"186\" width=\"42\" height=\"21\"/>\n                                <datePickerCell key=\"cell\" controlSize=\"large\" borderStyle=\"bezel\" alignment=\"left\" id=\"SSx-nM-n4a\">\n                                    <font key=\"font\" metaFont=\"system\"/>\n                                    <date key=\"date\" timeIntervalSinceReferenceDate=\"618901200.77973998\">\n                                        <!--2020-08-12 05:00:00 +0000-->\n                                    </date>\n                                    <color key=\"backgroundColor\" name=\"controlBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <datePickerElements key=\"datePickerElements\" hour=\"YES\" minute=\"YES\"/>\n                                </datePickerCell>\n                            </datePicker>\n                            <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"NHk-hd-Q4a\">\n                                <rect key=\"frame\" x=\"330\" y=\"190\" width=\"53\" height=\"17\"/>\n                                <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" title=\"Sunset:\" id=\"Rye-iX-Uy7\">\n                                    <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                    <color key=\"textColor\" name=\"secondaryLabelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                </textFieldCell>\n                            </textField>\n                            <textField verticalHuggingPriority=\"750\" horizontalCompressionResistancePriority=\"250\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"ohd-3z-kec\">\n                                <rect key=\"frame\" x=\"150\" y=\"102\" width=\"612\" height=\"17\"/>\n                                <textFieldCell key=\"cell\" selectable=\"YES\" title=\"Videos do not change based on the time of day. They will be played at random.\" id=\"Tv9-4o-QiS\">\n                                    <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                    <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                </textFieldCell>\n                            </textField>\n                            <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"6mZ-LV-nEO\">\n                                <rect key=\"frame\" x=\"535\" y=\"284\" width=\"249\" height=\"32\"/>\n                                <buttonCell key=\"cell\" type=\"push\" title=\"How to enable Location Services \" bezelStyle=\"rounded\" alignment=\"center\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"hFU-Be-EiQ\">\n                                    <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                                    <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                    <connections>\n                                        <action selector=\"locationServicesClick:\" target=\"-2\" id=\"DVi-ua-b4q\"/>\n                                    </connections>\n                                </buttonCell>\n                            </button>\n                        </subviews>\n                        <constraints>\n                            <constraint firstItem=\"8VH-do-LRN\" firstAttribute=\"leading\" secondItem=\"oA4-ui-9wq\" secondAttribute=\"leading\" id=\"413-D5-8Np\"/>\n                            <constraint firstAttribute=\"trailing\" secondItem=\"ohd-3z-kec\" secondAttribute=\"trailing\" constant=\"40\" id=\"7ej-m2-cSx\"/>\n                            <constraint firstItem=\"22t-gd-Abd\" firstAttribute=\"top\" secondItem=\"eZG-Mf-Rud\" secondAttribute=\"top\" id=\"9vH-Wt-cEp\"/>\n                            <constraint firstItem=\"3Nc-Pl-qMy\" firstAttribute=\"top\" secondItem=\"oA4-ui-9wq\" secondAttribute=\"bottom\" constant=\"20\" id=\"9wy-bM-HTA\"/>\n                            <constraint firstItem=\"6mZ-LV-nEO\" firstAttribute=\"leading\" secondItem=\"l3V-Qj-BKa\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"Gkv-n7-ebN\"/>\n                            <constraint firstItem=\"l3V-Qj-BKa\" firstAttribute=\"top\" secondItem=\"22t-gd-Abd\" secondAttribute=\"bottom\" constant=\"8\" symbolic=\"YES\" id=\"HQM-ai-fc8\"/>\n                            <constraint firstItem=\"fZE-lx-nSW\" firstAttribute=\"leading\" secondItem=\"Qil-A7-nRJ\" secondAttribute=\"leading\" constant=\"40\" id=\"Jbo-wF-Eci\"/>\n                            <constraint firstItem=\"utR-AS-8Il\" firstAttribute=\"leading\" secondItem=\"NHk-hd-Q4a\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"K9c-pr-uzR\"/>\n                            <constraint firstItem=\"6mZ-LV-nEO\" firstAttribute=\"firstBaseline\" secondItem=\"l3V-Qj-BKa\" secondAttribute=\"firstBaseline\" id=\"KFR-Sc-NI0\"/>\n                            <constraint firstItem=\"ohd-3z-kec\" firstAttribute=\"leading\" secondItem=\"uzu-Lk-YXP\" secondAttribute=\"trailing\" constant=\"64\" id=\"Q3P-OO-cvC\"/>\n                            <constraint firstItem=\"l3V-Qj-BKa\" firstAttribute=\"leading\" secondItem=\"eZG-Mf-Rud\" secondAttribute=\"trailing\" constant=\"64\" id=\"Rea-cF-U65\"/>\n                            <constraint firstItem=\"22t-gd-Abd\" firstAttribute=\"leading\" secondItem=\"eZG-Mf-Rud\" secondAttribute=\"trailing\" constant=\"40\" id=\"TJK-el-9qQ\"/>\n                            <constraint firstItem=\"FMY-kx-tOP\" firstAttribute=\"leading\" secondItem=\"8VH-do-LRN\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"VFy-bb-D5D\"/>\n                            <constraint firstItem=\"jHI-px-D0M\" firstAttribute=\"top\" secondItem=\"uzu-Lk-YXP\" secondAttribute=\"top\" id=\"VVz-MO-gAw\"/>\n                            <constraint firstItem=\"MX3-T8-nNh\" firstAttribute=\"top\" secondItem=\"fZE-lx-nSW\" secondAttribute=\"bottom\" constant=\"30\" id=\"WnF-mP-Lqb\"/>\n                            <constraint firstItem=\"FMY-kx-tOP\" firstAttribute=\"top\" secondItem=\"3Nc-Pl-qMy\" secondAttribute=\"bottom\" constant=\"20\" id=\"X2h-Xc-CGO\"/>\n                            <constraint firstItem=\"bGh-sP-GO3\" firstAttribute=\"leading\" secondItem=\"Qil-A7-nRJ\" secondAttribute=\"leading\" constant=\"40\" id=\"Zci-vr-UVD\"/>\n                            <constraint firstItem=\"uzu-Lk-YXP\" firstAttribute=\"leading\" secondItem=\"Qil-A7-nRJ\" secondAttribute=\"leading\" constant=\"40\" id=\"aAx-cw-aTr\"/>\n                            <constraint firstItem=\"fZE-lx-nSW\" firstAttribute=\"top\" secondItem=\"U3I-0O-JPu\" secondAttribute=\"bottom\" constant=\"30\" id=\"b30-Ic-o7O\"/>\n                            <constraint firstItem=\"ohd-3z-kec\" firstAttribute=\"top\" secondItem=\"jHI-px-D0M\" secondAttribute=\"bottom\" constant=\"8\" symbolic=\"YES\" id=\"bfh-FN-0G6\"/>\n                            <constraint firstItem=\"utR-AS-8Il\" firstAttribute=\"firstBaseline\" secondItem=\"8VH-do-LRN\" secondAttribute=\"firstBaseline\" id=\"bly-Yo-1dg\"/>\n                            <constraint firstItem=\"NHk-hd-Q4a\" firstAttribute=\"firstBaseline\" secondItem=\"8VH-do-LRN\" secondAttribute=\"firstBaseline\" id=\"cfa-Ao-7vK\"/>\n                            <constraint firstItem=\"3Nc-Pl-qMy\" firstAttribute=\"top\" secondItem=\"bGh-sP-GO3\" secondAttribute=\"top\" id=\"dF8-m6-vpl\"/>\n                            <constraint firstItem=\"U3I-0O-JPu\" firstAttribute=\"centerX\" secondItem=\"Qil-A7-nRJ\" secondAttribute=\"centerX\" id=\"dwG-AD-ldb\"/>\n                            <constraint firstItem=\"3Nc-Pl-qMy\" firstAttribute=\"leading\" secondItem=\"bGh-sP-GO3\" secondAttribute=\"trailing\" constant=\"40\" id=\"fOz-tS-Svd\"/>\n                            <constraint firstItem=\"NHk-hd-Q4a\" firstAttribute=\"leading\" secondItem=\"FMY-kx-tOP\" secondAttribute=\"trailing\" constant=\"80\" id=\"g0X-2G-wJt\"/>\n                            <constraint firstItem=\"oA4-ui-9wq\" firstAttribute=\"top\" secondItem=\"l3V-Qj-BKa\" secondAttribute=\"bottom\" constant=\"16\" id=\"iC8-Ko-pwO\"/>\n                            <constraint firstItem=\"jHI-px-D0M\" firstAttribute=\"top\" secondItem=\"FMY-kx-tOP\" secondAttribute=\"bottom\" constant=\"40\" id=\"lJO-5L-Pth\"/>\n                            <constraint firstItem=\"22t-gd-Abd\" firstAttribute=\"top\" secondItem=\"MX3-T8-nNh\" secondAttribute=\"bottom\" constant=\"40\" id=\"mtb-2q-eUB\"/>\n                            <constraint firstItem=\"eZG-Mf-Rud\" firstAttribute=\"leading\" secondItem=\"Qil-A7-nRJ\" secondAttribute=\"leading\" constant=\"40\" id=\"nCH-ee-RF1\"/>\n                            <constraint firstItem=\"MX3-T8-nNh\" firstAttribute=\"centerX\" secondItem=\"Qil-A7-nRJ\" secondAttribute=\"centerX\" id=\"qPz-gG-LLV\"/>\n                            <constraint firstAttribute=\"trailing\" secondItem=\"fZE-lx-nSW\" secondAttribute=\"trailing\" constant=\"40\" id=\"qcp-L3-2U4\"/>\n                            <constraint firstItem=\"U3I-0O-JPu\" firstAttribute=\"top\" secondItem=\"Qil-A7-nRJ\" secondAttribute=\"top\" constant=\"20\" id=\"u0Z-8v-vkg\"/>\n                            <constraint firstItem=\"jHI-px-D0M\" firstAttribute=\"leading\" secondItem=\"uzu-Lk-YXP\" secondAttribute=\"trailing\" constant=\"40\" id=\"upN-4h-zUp\"/>\n                            <constraint firstItem=\"FMY-kx-tOP\" firstAttribute=\"firstBaseline\" secondItem=\"8VH-do-LRN\" secondAttribute=\"firstBaseline\" id=\"vF3-9z-Dcv\"/>\n                            <constraint firstItem=\"oA4-ui-9wq\" firstAttribute=\"leading\" secondItem=\"l3V-Qj-BKa\" secondAttribute=\"leading\" id=\"ySW-uS-7w0\"/>\n                        </constraints>\n                    </view>\n                    <color key=\"borderColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    <color key=\"fillColor\" name=\"windowBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                </box>\n            </subviews>\n            <constraints>\n                <constraint firstItem=\"KeN-Yr-ChJ\" firstAttribute=\"top\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"top\" id=\"AUY-E7-QuR\"/>\n                <constraint firstItem=\"KeN-Yr-ChJ\" firstAttribute=\"leading\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"leading\" id=\"nSu-W0-e9R\"/>\n                <constraint firstAttribute=\"bottom\" secondItem=\"KeN-Yr-ChJ\" secondAttribute=\"bottom\" id=\"qI3-CB-ljB\"/>\n                <constraint firstAttribute=\"trailing\" secondItem=\"KeN-Yr-ChJ\" secondAttribute=\"trailing\" id=\"yRX-WN-7eK\"/>\n            </constraints>\n            <point key=\"canvasLocation\" x=\"-169\" y=\"154\"/>\n        </customView>\n    </objects>\n    <resources>\n        <image name=\"clock\" width=\"141\" height=\"155\"/>\n        <image name=\"mappin.and.ellipse\" width=\"133\" height=\"173\"/>\n        <image name=\"moon.stars\" width=\"136\" height=\"136\"/>\n        <image name=\"sun.max\" width=\"147\" height=\"168\"/>\n        <image name=\"sunrise\" width=\"180\" height=\"133\"/>\n        <image name=\"sunset\" width=\"180\" height=\"133\"/>\n        <image name=\"xmark.circle\" width=\"141\" height=\"155\"/>\n    </resources>\n</document>\n"
  },
  {
    "path": "Resources/MainUI/First time setup/VideoFormatViewController.swift",
    "content": "//\n//  VideoFormatViewController.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 11/08/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Cocoa\nimport AVKit\n\nclass VideoFormatViewController: NSViewController {\n\n    @IBOutlet var videoFormatPopup: NSPopUpButton!\n    @IBOutlet var previewView: AVPlayerView!\n    // We need to hide HDR pre-Catalina\n    @IBOutlet var menu1080pHDR: NSMenuItem!\n    @IBOutlet var menu4KHDR: NSMenuItem!\n\n    @IBOutlet var labelBelow: NSTextField!\n    var currentVideo: AerialVideo?\n\n    @IBOutlet var warnImage: NSImageView!\n    @IBOutlet var warnLabel: NSTextField!\n    var originalFormat: VideoFormat?\n    override func viewDidLoad() {\n        super.viewDidLoad()\n\n        // We need catalina for HDR !\n        if #available(OSX 10.15, *) {\n        } else {\n            menu1080pHDR.isHidden = true\n            menu4KHDR.isHidden = true\n        }\n\n        warnLabel.isHidden = true\n        warnImage.isHidden = true\n\n        // Only detect if we have the default basic format, don't override people's settings\n        if PrefsVideos.videoFormat == .v1080pH264 {\n            PrefsVideos.videoFormat = HardwareDetection.sharedInstance.getSuggestedFormat()\n        } else {\n            labelBelow.stringValue = \"Videos are usually available in multiple formats. Your current format is preselected, but you can pick another one.\"\n            originalFormat = PrefsVideos.videoFormat\n        }\n        videoFormatPopup.selectItem(at: PrefsVideos.videoFormat.rawValue)\n\n        previewView.player = AVPlayer()\n        previewView.showsFullScreenToggleButton = true\n        // previewView.controlsStyle = .none\n        if #available(OSX 10.10, *) {\n            previewView.videoGravity = .resizeAspectFill\n        }\n\n        getNewVideo()\n        setupPlayer()\n    }\n\n    @IBAction func moreInfoFormats(_ sender: Any) {\n        let workspace = NSWorkspace.shared\n        let url = URL(string: \"https://github.com/JohnCoates/Aerial/blob/master/Documentation/HardwareDecoding.md\")!\n        workspace.open(url)\n    }\n\n    @IBAction func newVideoClick(_ sender: Any) {\n        getNewVideo()\n        setupPlayer()\n    }\n\n    @IBAction func formatChange(_ sender: NSPopUpButton) {\n        if let original = originalFormat {\n            let candidateFormat = VideoFormat(rawValue: sender.indexOfSelectedItem)!\n\n            if candidateFormat != original {\n                warnLabel.isHidden = false\n                warnImage.isHidden = false\n            } else {\n                warnLabel.isHidden = true\n                warnImage.isHidden = true\n            }\n        }\n\n        PrefsVideos.videoFormat = VideoFormat(rawValue: sender.indexOfSelectedItem)!\n        setupPlayer()\n    }\n\n    func setupPlayer() {\n        if let player = previewView.player {\n            if let video = currentVideo {\n                player.pause()\n\n                if let onlineUrl = URL(string: (video.urls[PrefsVideos.videoFormat])!) {\n                    let asset = AVAsset(url: onlineUrl)\n                    let item = AVPlayerItem(asset: asset)\n                    player.replaceCurrentItem(with: item)\n                    player.play()\n                }\n            }\n        }\n    }\n\n    // Get a random video available in all format\n    func getNewVideo() {\n        currentVideo = VideoList.instance.videos.filter({ $0.hasHDR() == true }).shuffled().first\n    }\n}\n"
  },
  {
    "path": "Resources/MainUI/First time setup/VideoFormatViewController.xib",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.Cocoa.XIB\" version=\"3.0\" toolsVersion=\"19529\" targetRuntime=\"MacOSX.Cocoa\" propertyAccessControl=\"none\" useAutolayout=\"YES\" customObjectInstantitationMethod=\"direct\">\n    <dependencies>\n        <deployment identifier=\"macosx\"/>\n        <plugIn identifier=\"com.apple.AVKitIBPlugin\" version=\"19529\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.CocoaPlugin\" version=\"19529\"/>\n        <capability name=\"documents saved in the Xcode 8 format\" minToolsVersion=\"8.0\"/>\n    </dependencies>\n    <objects>\n        <customObject id=\"-2\" userLabel=\"File's Owner\" customClass=\"VideoFormatViewController\" customModule=\"Aerial\" customModuleProvider=\"target\">\n            <connections>\n                <outlet property=\"labelBelow\" destination=\"6kN-6G-HaO\" id=\"vlK-5K-lhL\"/>\n                <outlet property=\"menu1080pHDR\" destination=\"Idp-Kd-bOv\" id=\"diD-tN-SmL\"/>\n                <outlet property=\"menu4KHDR\" destination=\"qIp-VJ-XaI\" id=\"b4a-TD-otf\"/>\n                <outlet property=\"previewView\" destination=\"GSb-Cu-pqq\" id=\"WCe-p2-0Pb\"/>\n                <outlet property=\"videoFormatPopup\" destination=\"bCn-bE-tfP\" id=\"BVk-Ts-QmH\"/>\n                <outlet property=\"view\" destination=\"Hz6-mo-xeY\" id=\"0bl-1N-x8E\"/>\n                <outlet property=\"warnImage\" destination=\"0iL-7l-ydg\" id=\"Fhe-Qf-HcK\"/>\n                <outlet property=\"warnLabel\" destination=\"Vgr-Xc-TCM\" id=\"TE4-x9-IRW\"/>\n            </connections>\n        </customObject>\n        <customObject id=\"-1\" userLabel=\"First Responder\" customClass=\"FirstResponder\"/>\n        <customObject id=\"-3\" userLabel=\"Application\" customClass=\"NSObject\"/>\n        <customView id=\"Hz6-mo-xeY\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"800\" height=\"600\"/>\n            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n            <subviews>\n                <box boxType=\"custom\" borderType=\"none\" borderWidth=\"0.0\" title=\"Box\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Jpp-Xv-BLW\">\n                    <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"800\" height=\"600\"/>\n                    <view key=\"contentView\" id=\"C0g-r8-O2P\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"800\" height=\"600\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <subviews>\n                            <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"4Ev-9E-map\">\n                                <rect key=\"frame\" x=\"287\" y=\"537\" width=\"227\" height=\"43\"/>\n                                <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"Video Format\" id=\"LQR-oP-PgL\">\n                                    <font key=\"font\" metaFont=\"systemBold\" size=\"36\"/>\n                                    <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                </textFieldCell>\n                            </textField>\n                            <avPlayerView controlsStyle=\"inline\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"GSb-Cu-pqq\">\n                                <rect key=\"frame\" x=\"40\" y=\"112\" width=\"720\" height=\"405\"/>\n                                <constraints>\n                                    <constraint firstAttribute=\"width\" secondItem=\"GSb-Cu-pqq\" secondAttribute=\"height\" multiplier=\"16:9\" id=\"iTr-TX-whH\"/>\n                                </constraints>\n                            </avPlayerView>\n                            <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"6kN-6G-HaO\">\n                                <rect key=\"frame\" x=\"38\" y=\"45\" width=\"364\" height=\"51\"/>\n                                <constraints>\n                                    <constraint firstAttribute=\"width\" constant=\"360\" id=\"c2X-yS-kur\"/>\n                                </constraints>\n                                <textFieldCell key=\"cell\" id=\"vfq-Bk-gYA\">\n                                    <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                    <string key=\"title\">Videos are usually available in multiple formats. We've preselected the most energy efficient format for your machine below, but you can pick another one.</string>\n                                    <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                </textFieldCell>\n                            </textField>\n                            <popUpButton toolTip=\"Pick your preferred video format, see help for more information\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"bCn-bE-tfP\">\n                                <rect key=\"frame\" x=\"411\" y=\"62\" width=\"131\" height=\"40\"/>\n                                <popUpButtonCell key=\"cell\" type=\"push\" title=\"1080p H264\" bezelStyle=\"rounded\" alignment=\"left\" controlSize=\"large\" lineBreakMode=\"truncatingTail\" state=\"on\" borderStyle=\"borderAndBezel\" imageScaling=\"proportionallyDown\" inset=\"2\" selectedItem=\"U5B-t8-1pa\" id=\"GVh-Ib-AYr\">\n                                    <behavior key=\"behavior\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                                    <font key=\"font\" size=\"14\" name=\"HelveticaNeue\"/>\n                                    <menu key=\"menu\" id=\"J1D-DR-kUn\">\n                                        <items>\n                                            <menuItem title=\"1080p H264\" state=\"on\" id=\"U5B-t8-1pa\"/>\n                                            <menuItem title=\"1080p HEVC\" id=\"1FC-Bt-deB\"/>\n                                            <menuItem title=\"1080p HDR\" id=\"Idp-Kd-bOv\" userLabel=\"1080p HDR\">\n                                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            </menuItem>\n                                            <menuItem title=\"4K HEVC\" id=\"nAG-eX-Oto\"/>\n                                            <menuItem title=\"4K HDR\" id=\"qIp-VJ-XaI\" userLabel=\"4K HDR\">\n                                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            </menuItem>\n                                        </items>\n                                    </menu>\n                                </popUpButtonCell>\n                                <connections>\n                                    <action selector=\"formatChange:\" target=\"-2\" id=\"s6a-MD-zVI\"/>\n                                </connections>\n                            </popUpButton>\n                            <button toolTip=\"Get another video\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"8u2-wX-Sf9\">\n                                <rect key=\"frame\" x=\"724\" y=\"62\" width=\"42\" height=\"40\"/>\n                                <buttonCell key=\"cell\" type=\"push\" bezelStyle=\"rounded\" image=\"NSRefreshTemplate\" imagePosition=\"only\" alignment=\"center\" controlSize=\"large\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"4Jd-Sf-wLD\">\n                                    <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                                    <font key=\"font\" metaFont=\"system\"/>\n                                </buttonCell>\n                                <connections>\n                                    <action selector=\"newVideoClick:\" target=\"-2\" id=\"ASf-9s-qYh\"/>\n                                </connections>\n                            </button>\n                            <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"YqF-HA-cLA\">\n                                <rect key=\"frame\" x=\"414\" y=\"22\" width=\"372\" height=\"30\"/>\n                                <textFieldCell key=\"cell\" controlSize=\"large\" title=\"You can expand the video to full screen by passing your cursor over the video and choosing the arrows in the upper left corner\" id=\"Z5K-mZ-raw\">\n                                    <font key=\"font\" metaFont=\"cellTitle\"/>\n                                    <color key=\"textColor\" name=\"secondaryLabelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                </textFieldCell>\n                            </textField>\n                            <imageView horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"0iL-7l-ydg\">\n                                <rect key=\"frame\" x=\"545\" y=\"71\" width=\"22\" height=\"22\"/>\n                                <constraints>\n                                    <constraint firstAttribute=\"height\" constant=\"22\" id=\"3MG-ih-7bh\"/>\n                                    <constraint firstAttribute=\"width\" constant=\"22\" id=\"wTo-HH-AWI\"/>\n                                </constraints>\n                                <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" image=\"NSCaution\" id=\"JGy-xG-REQ\"/>\n                            </imageView>\n                            <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Vgr-Xc-TCM\">\n                                <rect key=\"frame\" x=\"573\" y=\"75\" width=\"148\" height=\"16\"/>\n                                <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"Your cache will be reset\" id=\"heS-D0-oJd\">\n                                    <font key=\"font\" metaFont=\"system\"/>\n                                    <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                </textFieldCell>\n                            </textField>\n                            <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"T3G-wH-SHI\">\n                                <rect key=\"frame\" x=\"40\" y=\"14\" width=\"303\" height=\"19\"/>\n                                <buttonCell key=\"cell\" type=\"roundRect\" title=\"More Information on Available Video Formats\" bezelStyle=\"roundedRect\" image=\"buttonCell:orG-5Q-EPo:image\" imagePosition=\"overlaps\" alignment=\"center\" controlSize=\"large\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"orG-5Q-EPo\">\n                                    <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                                    <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                </buttonCell>\n                                <connections>\n                                    <action selector=\"moreInfoFormats:\" target=\"-2\" id=\"vW3-gr-M7b\"/>\n                                </connections>\n                            </button>\n                        </subviews>\n                        <constraints>\n                            <constraint firstItem=\"0iL-7l-ydg\" firstAttribute=\"leading\" secondItem=\"bCn-bE-tfP\" secondAttribute=\"trailing\" constant=\"8\" id=\"59c-qQ-Flf\"/>\n                            <constraint firstItem=\"6kN-6G-HaO\" firstAttribute=\"leading\" secondItem=\"C0g-r8-O2P\" secondAttribute=\"leading\" constant=\"40\" id=\"CJY-zL-H9e\"/>\n                            <constraint firstItem=\"bCn-bE-tfP\" firstAttribute=\"leading\" secondItem=\"6kN-6G-HaO\" secondAttribute=\"trailing\" constant=\"16\" id=\"GbB-Z2-vHi\"/>\n                            <constraint firstItem=\"bCn-bE-tfP\" firstAttribute=\"top\" secondItem=\"6kN-6G-HaO\" secondAttribute=\"top\" id=\"KGY-NW-vye\"/>\n                            <constraint firstItem=\"0iL-7l-ydg\" firstAttribute=\"centerY\" secondItem=\"bCn-bE-tfP\" secondAttribute=\"centerY\" id=\"Nmd-SG-HYI\"/>\n                            <constraint firstItem=\"YqF-HA-cLA\" firstAttribute=\"leading\" secondItem=\"bCn-bE-tfP\" secondAttribute=\"leading\" id=\"Tbr-mW-2er\"/>\n                            <constraint firstItem=\"8u2-wX-Sf9\" firstAttribute=\"top\" secondItem=\"bCn-bE-tfP\" secondAttribute=\"top\" id=\"XCE-Y9-a5K\"/>\n                            <constraint firstItem=\"GSb-Cu-pqq\" firstAttribute=\"leading\" secondItem=\"C0g-r8-O2P\" secondAttribute=\"leading\" constant=\"40\" id=\"Zyx-96-OQ3\"/>\n                            <constraint firstItem=\"GSb-Cu-pqq\" firstAttribute=\"top\" secondItem=\"4Ev-9E-map\" secondAttribute=\"bottom\" constant=\"20\" id=\"api-sN-cka\"/>\n                            <constraint firstAttribute=\"bottom\" secondItem=\"6kN-6G-HaO\" secondAttribute=\"bottom\" constant=\"45\" id=\"h2F-Fi-fwf\"/>\n                            <constraint firstItem=\"Vgr-Xc-TCM\" firstAttribute=\"firstBaseline\" secondItem=\"bCn-bE-tfP\" secondAttribute=\"firstBaseline\" id=\"m4g-0L-rE4\"/>\n                            <constraint firstItem=\"4Ev-9E-map\" firstAttribute=\"top\" secondItem=\"C0g-r8-O2P\" secondAttribute=\"top\" constant=\"20\" id=\"mZW-JF-UWh\"/>\n                            <constraint firstItem=\"4Ev-9E-map\" firstAttribute=\"centerX\" secondItem=\"C0g-r8-O2P\" secondAttribute=\"centerX\" id=\"olh-56-nDR\"/>\n                            <constraint firstAttribute=\"trailing\" secondItem=\"YqF-HA-cLA\" secondAttribute=\"trailing\" constant=\"16\" id=\"qaY-KI-NYv\"/>\n                            <constraint firstItem=\"T3G-wH-SHI\" firstAttribute=\"top\" secondItem=\"6kN-6G-HaO\" secondAttribute=\"bottom\" constant=\"12\" id=\"qcz-bg-Xuc\"/>\n                            <constraint firstItem=\"Vgr-Xc-TCM\" firstAttribute=\"leading\" secondItem=\"0iL-7l-ydg\" secondAttribute=\"trailing\" constant=\"8\" id=\"sp4-Lj-wGv\"/>\n                            <constraint firstItem=\"YqF-HA-cLA\" firstAttribute=\"top\" secondItem=\"bCn-bE-tfP\" secondAttribute=\"bottom\" constant=\"16\" id=\"uoi-Ve-cib\"/>\n                            <constraint firstItem=\"8u2-wX-Sf9\" firstAttribute=\"trailing\" secondItem=\"GSb-Cu-pqq\" secondAttribute=\"trailing\" id=\"y99-F7-38s\"/>\n                            <constraint firstItem=\"T3G-wH-SHI\" firstAttribute=\"leading\" secondItem=\"C0g-r8-O2P\" secondAttribute=\"leading\" constant=\"40\" id=\"zGb-24-rCP\"/>\n                            <constraint firstAttribute=\"trailing\" secondItem=\"GSb-Cu-pqq\" secondAttribute=\"trailing\" constant=\"40\" id=\"zyU-nm-Ip5\"/>\n                        </constraints>\n                    </view>\n                    <constraints>\n                        <constraint firstAttribute=\"width\" constant=\"800\" id=\"mhh-Yb-L5T\"/>\n                        <constraint firstAttribute=\"height\" constant=\"600\" id=\"xHY-By-Xsz\"/>\n                    </constraints>\n                    <color key=\"borderColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"0.84705882349999995\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                    <color key=\"fillColor\" name=\"windowBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                </box>\n            </subviews>\n            <constraints>\n                <constraint firstAttribute=\"bottom\" secondItem=\"Jpp-Xv-BLW\" secondAttribute=\"bottom\" id=\"2jn-G3-vsC\"/>\n                <constraint firstItem=\"Jpp-Xv-BLW\" firstAttribute=\"top\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"top\" id=\"3a9-6R-BNP\"/>\n                <constraint firstItem=\"Jpp-Xv-BLW\" firstAttribute=\"leading\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"leading\" id=\"UUv-ug-hg2\"/>\n                <constraint firstAttribute=\"trailing\" secondItem=\"Jpp-Xv-BLW\" secondAttribute=\"trailing\" id=\"YnB-p0-gm7\"/>\n            </constraints>\n            <point key=\"canvasLocation\" x=\"3\" y=\"137\"/>\n        </customView>\n    </objects>\n    <resources>\n        <image name=\"NSCaution\" width=\"32\" height=\"32\"/>\n        <image name=\"NSRefreshTemplate\" width=\"14\" height=\"16\"/>\n        <image name=\"buttonCell:orG-5Q-EPo:image\" width=\"1\" height=\"1\">\n            <mutableData key=\"keyedArchiveRepresentation\">\nYnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMSAAGGoF8QD05T\nS2V5ZWRBcmNoaXZlctEICVRyb290gAGvEBcLDBkaIRQmKywzNjs+P0RHSEtVXV5iZVUkbnVsbNYNDg8Q\nERITFBUWFxhWTlNTaXplXk5TUmVzaXppbmdNb2RlViRjbGFzc1xOU0ltYWdlRmxhZ3NWTlNSZXBzV05T\nQ29sb3KAAhAAgBYSIMMAAIADgBFWezEsIDF90hsPHCBaTlMub2JqZWN0c6MdHh+ABIAKgA2AENIbDyIl\noiMkgAWABoAJ0w8nKCkqFF8QFE5TVElGRlJlcHJlc2VudGF0aW9uXxAZTlNJbnRlcm5hbExheW91dERp\ncmVjdGlvboAIgAdPEQ0qTU0AKgAAAAwAAAAAABABAAADAAAAAQABAAABAQADAAAAAQABAAABAgADAAAA\nBAAAANIBAwADAAAAAQABAAABBgADAAAAAQACAAABCgADAAAAAQABAAABEQAEAAAAAQAAAAgBEgADAAAA\nAQABAAABFQADAAAAAQAEAAABFgADAAAAAQABAAABFwAEAAAAAQAAAAQBHAADAAAAAQABAAABKAADAAAA\nAQACAAABUgADAAAAAQABAAABUwADAAAABAAAANqHcwAHAAAMSAAAAOIAAAAAAAgACAAIAAgAAQABAAEA\nAQAADEhMaW5vAhAAAG1udHJSR0IgWFlaIAfOAAIACQAGADEAAGFjc3BNU0ZUAAAAAElFQyBzUkdCAAAA\nAAAAAAAAAAAAAAD21gABAAAAANMtSFAgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAEWNwcnQAAAFQAAAAM2Rlc2MAAAGEAAAAbHd0cHQAAAHwAAAAFGJrcHQAAAIEAAAA\nFHJYWVoAAAIYAAAAFGdYWVoAAAIsAAAAFGJYWVoAAAJAAAAAFGRtbmQAAAJUAAAAcGRtZGQAAALEAAAA\niHZ1ZWQAAANMAAAAhnZpZXcAAAPUAAAAJGx1bWkAAAP4AAAAFG1lYXMAAAQMAAAAJHRlY2gAAAQwAAAA\nDHJUUkMAAAQ8AAAIDGdUUkMAAAQ8AAAIDGJUUkMAAAQ8AAAIDHRleHQAAAAAQ29weXJpZ2h0IChjKSAx\nOTk4IEhld2xldHQtUGFja2FyZCBDb21wYW55AABkZXNjAAAAAAAAABJzUkdCIElFQzYxOTY2LTIuMQAA\nAAAAAAAAAAAAEnNSR0IgSUVDNjE5NjYtMi4xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAABYWVogAAAAAAAA81EAAQAAAAEWzFhZWiAAAAAAAAAAAAAAAAAAAAAAWFla\nIAAAAAAAAG+iAAA49QAAA5BYWVogAAAAAAAAYpkAALeFAAAY2lhZWiAAAAAAAAAkoAAAD4QAALbPZGVz\nYwAAAAAAAAAWSUVDIGh0dHA6Ly93d3cuaWVjLmNoAAAAAAAAAAAAAAAWSUVDIGh0dHA6Ly93d3cuaWVj\nLmNoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGRlc2MAAAAAAAAA\nLklFQyA2MTk2Ni0yLjEgRGVmYXVsdCBSR0IgY29sb3VyIHNwYWNlIC0gc1JHQgAAAAAAAAAAAAAALklF\nQyA2MTk2Ni0yLjEgRGVmYXVsdCBSR0IgY29sb3VyIHNwYWNlIC0gc1JHQgAAAAAAAAAAAAAAAAAAAAAA\nAAAAAABkZXNjAAAAAAAAACxSZWZlcmVuY2UgVmlld2luZyBDb25kaXRpb24gaW4gSUVDNjE5NjYtMi4x\nAAAAAAAAAAAAAAAsUmVmZXJlbmNlIFZpZXdpbmcgQ29uZGl0aW9uIGluIElFQzYxOTY2LTIuMQAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAdmlldwAAAAAAE6T+ABRfLgAQzxQAA+3MAAQTCwADXJ4AAAABWFla\nIAAAAAAATAlWAFAAAABXH+dtZWFzAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAACjwAAAAJzaWcgAAAA\nAENSVCBjdXJ2AAAAAAAABAAAAAAFAAoADwAUABkAHgAjACgALQAyADcAOwBAAEUASgBPAFQAWQBeAGMA\naABtAHIAdwB8AIEAhgCLAJAAlQCaAJ8ApACpAK4AsgC3ALwAwQDGAMsA0ADVANsA4ADlAOsA8AD2APsB\nAQEHAQ0BEwEZAR8BJQErATIBOAE+AUUBTAFSAVkBYAFnAW4BdQF8AYMBiwGSAZoBoQGpAbEBuQHBAckB\n0QHZAeEB6QHyAfoCAwIMAhQCHQImAi8COAJBAksCVAJdAmcCcQJ6AoQCjgKYAqICrAK2AsECywLVAuAC\n6wL1AwADCwMWAyEDLQM4A0MDTwNaA2YDcgN+A4oDlgOiA64DugPHA9MD4APsA/kEBgQTBCAELQQ7BEgE\nVQRjBHEEfgSMBJoEqAS2BMQE0wThBPAE/gUNBRwFKwU6BUkFWAVnBXcFhgWWBaYFtQXFBdUF5QX2BgYG\nFgYnBjcGSAZZBmoGewaMBp0GrwbABtEG4wb1BwcHGQcrBz0HTwdhB3QHhgeZB6wHvwfSB+UH+AgLCB8I\nMghGCFoIbgiCCJYIqgi+CNII5wj7CRAJJQk6CU8JZAl5CY8JpAm6Cc8J5Qn7ChEKJwo9ClQKagqBCpgK\nrgrFCtwK8wsLCyILOQtRC2kLgAuYC7ALyAvhC/kMEgwqDEMMXAx1DI4MpwzADNkM8w0NDSYNQA1aDXQN\njg2pDcMN3g34DhMOLg5JDmQOfw6bDrYO0g7uDwkPJQ9BD14Peg+WD7MPzw/sEAkQJhBDEGEQfhCbELkQ\n1xD1ERMRMRFPEW0RjBGqEckR6BIHEiYSRRJkEoQSoxLDEuMTAxMjE0MTYxODE6QTxRPlFAYUJxRJFGoU\nixStFM4U8BUSFTQVVhV4FZsVvRXgFgMWJhZJFmwWjxayFtYW+hcdF0EXZReJF64X0hf3GBsYQBhlGIoY\nrxjVGPoZIBlFGWsZkRm3Gd0aBBoqGlEadxqeGsUa7BsUGzsbYxuKG7Ib2hwCHCocUhx7HKMczBz1HR4d\nRx1wHZkdwx3sHhYeQB5qHpQevh7pHxMfPh9pH5Qfvx/qIBUgQSBsIJggxCDwIRwhSCF1IaEhziH7Iici\nVSKCIq8i3SMKIzgjZiOUI8Ij8CQfJE0kfCSrJNolCSU4JWgllyXHJfcmJyZXJocmtyboJxgnSSd6J6sn\n3CgNKD8ocSiiKNQpBik4KWspnSnQKgIqNSpoKpsqzysCKzYraSudK9EsBSw5LG4soizXLQwtQS12Last\n4S4WLkwugi63Lu4vJC9aL5Evxy/+MDUwbDCkMNsxEjFKMYIxujHyMioyYzKbMtQzDTNGM38zuDPxNCs0\nZTSeNNg1EzVNNYc1wjX9Njc2cjauNuk3JDdgN5w31zgUOFA4jDjIOQU5Qjl/Obw5+To2OnQ6sjrvOy07\nazuqO+g8JzxlPKQ84z0iPWE9oT3gPiA+YD6gPuA/IT9hP6I/4kAjQGRApkDnQSlBakGsQe5CMEJyQrVC\n90M6Q31DwEQDREdEikTORRJFVUWaRd5GIkZnRqtG8Ec1R3tHwEgFSEtIkUjXSR1JY0mpSfBKN0p9SsRL\nDEtTS5pL4kwqTHJMuk0CTUpNk03cTiVObk63TwBPSU+TT91QJ1BxULtRBlFQUZtR5lIxUnxSx1MTU19T\nqlP2VEJUj1TbVShVdVXCVg9WXFapVvdXRFeSV+BYL1h9WMtZGllpWbhaB1pWWqZa9VtFW5Vb5Vw1XIZc\n1l0nXXhdyV4aXmxevV8PX2Ffs2AFYFdgqmD8YU9homH1YklinGLwY0Njl2PrZEBklGTpZT1lkmXnZj1m\nkmboZz1nk2fpaD9olmjsaUNpmmnxakhqn2r3a09rp2v/bFdsr20IbWBtuW4SbmtuxG8eb3hv0XArcIZw\n4HE6cZVx8HJLcqZzAXNdc7h0FHRwdMx1KHWFdeF2Pnabdvh3VnezeBF4bnjMeSp5iXnnekZ6pXsEe2N7\nwnwhfIF84X1BfaF+AX5ifsJ/I3+Ef+WAR4CogQqBa4HNgjCCkoL0g1eDuoQdhICE44VHhauGDoZyhteH\nO4efiASIaYjOiTOJmYn+imSKyoswi5aL/IxjjMqNMY2Yjf+OZo7OjzaPnpAGkG6Q1pE/kaiSEZJ6kuOT\nTZO2lCCUipT0lV+VyZY0lp+XCpd1l+CYTJi4mSSZkJn8mmia1ZtCm6+cHJyJnPedZJ3SnkCerp8dn4uf\n+qBpoNihR6G2oiailqMGo3aj5qRWpMelOKWpphqmi6b9p26n4KhSqMSpN6mpqhyqj6sCq3Wr6axcrNCt\nRK24ri2uoa8Wr4uwALB1sOqxYLHWskuywrM4s660JbSctRO1irYBtnm28Ldot+C4WbjRuUq5wro7urW7\nLrunvCG8m70VvY++Cr6Evv+/er/1wHDA7MFnwePCX8Lbw1jD1MRRxM7FS8XIxkbGw8dBx7/IPci8yTrJ\nuco4yrfLNsu2zDXMtc01zbXONs62zzfPuNA50LrRPNG+0j/SwdNE08bUSdTL1U7V0dZV1tjXXNfg2GTY\n6Nls2fHadtr724DcBdyK3RDdlt4c3qLfKd+v4DbgveFE4cziU+Lb42Pj6+Rz5PzlhOYN5pbnH+ep6DLo\nvOlG6dDqW+rl63Dr++yG7RHtnO4o7rTvQO/M8Fjw5fFy8f/yjPMZ86f0NPTC9VD13vZt9vv3ivgZ+Kj5\nOPnH+lf65/t3/Af8mP0p/br+S/7c/23//9ItLi8wWiRjbGFzc25hbWVYJGNsYXNzZXNfEBBOU0JpdG1h\ncEltYWdlUmVwoy8xMlpOU0ltYWdlUmVwWE5TT2JqZWN00i0uNDVXTlNBcnJheaI0MtIbDzcloiM5gAWA\nC4AJ0w8nKCk9FIAIgAxPEQ1eTU0AKgAAABgAAAAAAAAAAAAAAAAAAAAAABIBAAADAAAAAQACAAABAQAD\nAAAAAQACAAABAgADAAAABAAAAQYBAwADAAAAAQABAAABBgADAAAAAQACAAABCgADAAAAAQABAAABEQAE\nAAAAAQAAAAgBEgADAAAAAQABAAABFQADAAAAAQAEAAABFgADAAAAAQACAAABFwAEAAAAAQAAABABGgAF\nAAAAAQAAAPYBGwAFAAAAAQAAAP4BHAADAAAAAQABAAABKAADAAAAAQACAAABUgADAAAAAQABAAABUwAD\nAAAABAAAAQ6HcwAHAAAMSAAAARYAAAAAAAAAkAAAAAEAAACQAAAAAQAIAAgACAAIAAEAAQABAAEAAAxI\nTGlubwIQAABtbnRyUkdCIFhZWiAHzgACAAkABgAxAABhY3NwTVNGVAAAAABJRUMgc1JHQgAAAAAAAAAA\nAAAAAAAA9tYAAQAAAADTLUhQICAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAABFjcHJ0AAABUAAAADNkZXNjAAABhAAAAGx3dHB0AAAB8AAAABRia3B0AAACBAAAABRyWFla\nAAACGAAAABRnWFlaAAACLAAAABRiWFlaAAACQAAAABRkbW5kAAACVAAAAHBkbWRkAAACxAAAAIh2dWVk\nAAADTAAAAIZ2aWV3AAAD1AAAACRsdW1pAAAD+AAAABRtZWFzAAAEDAAAACR0ZWNoAAAEMAAAAAxyVFJD\nAAAEPAAACAxnVFJDAAAEPAAACAxiVFJDAAAEPAAACAx0ZXh0AAAAAENvcHlyaWdodCAoYykgMTk5OCBI\nZXdsZXR0LVBhY2thcmQgQ29tcGFueQAAZGVzYwAAAAAAAAASc1JHQiBJRUM2MTk2Ni0yLjEAAAAAAAAA\nAAAAABJzUkdCIElFQzYxOTY2LTIuMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAWFlaIAAAAAAAAPNRAAEAAAABFsxYWVogAAAAAAAAAAAAAAAAAAAAAFhZWiAAAAAA\nAABvogAAOPUAAAOQWFlaIAAAAAAAAGKZAAC3hQAAGNpYWVogAAAAAAAAJKAAAA+EAAC2z2Rlc2MAAAAA\nAAAAFklFQyBodHRwOi8vd3d3LmllYy5jaAAAAAAAAAAAAAAAFklFQyBodHRwOi8vd3d3LmllYy5jaAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABkZXNjAAAAAAAAAC5JRUMg\nNjE5NjYtMi4xIERlZmF1bHQgUkdCIGNvbG91ciBzcGFjZSAtIHNSR0IAAAAAAAAAAAAAAC5JRUMgNjE5\nNjYtMi4xIERlZmF1bHQgUkdCIGNvbG91ciBzcGFjZSAtIHNSR0IAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nZGVzYwAAAAAAAAAsUmVmZXJlbmNlIFZpZXdpbmcgQ29uZGl0aW9uIGluIElFQzYxOTY2LTIuMQAAAAAA\nAAAAAAAALFJlZmVyZW5jZSBWaWV3aW5nIENvbmRpdGlvbiBpbiBJRUM2MTk2Ni0yLjEAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAHZpZXcAAAAAABOk/gAUXy4AEM8UAAPtzAAEEwsAA1yeAAAAAVhZWiAAAAAA\nAEwJVgBQAAAAVx/nbWVhcwAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAo8AAAACc2lnIAAAAABDUlQg\nY3VydgAAAAAAAAQAAAAABQAKAA8AFAAZAB4AIwAoAC0AMgA3ADsAQABFAEoATwBUAFkAXgBjAGgAbQBy\nAHcAfACBAIYAiwCQAJUAmgCfAKQAqQCuALIAtwC8AMEAxgDLANAA1QDbAOAA5QDrAPAA9gD7AQEBBwEN\nARMBGQEfASUBKwEyATgBPgFFAUwBUgFZAWABZwFuAXUBfAGDAYsBkgGaAaEBqQGxAbkBwQHJAdEB2QHh\nAekB8gH6AgMCDAIUAh0CJgIvAjgCQQJLAlQCXQJnAnECegKEAo4CmAKiAqwCtgLBAssC1QLgAusC9QMA\nAwsDFgMhAy0DOANDA08DWgNmA3IDfgOKA5YDogOuA7oDxwPTA+AD7AP5BAYEEwQgBC0EOwRIBFUEYwRx\nBH4EjASaBKgEtgTEBNME4QTwBP4FDQUcBSsFOgVJBVgFZwV3BYYFlgWmBbUFxQXVBeUF9gYGBhYGJwY3\nBkgGWQZqBnsGjAadBq8GwAbRBuMG9QcHBxkHKwc9B08HYQd0B4YHmQesB78H0gflB/gICwgfCDIIRgha\nCG4IggiWCKoIvgjSCOcI+wkQCSUJOglPCWQJeQmPCaQJugnPCeUJ+woRCicKPQpUCmoKgQqYCq4KxQrc\nCvMLCwsiCzkLUQtpC4ALmAuwC8gL4Qv5DBIMKgxDDFwMdQyODKcMwAzZDPMNDQ0mDUANWg10DY4NqQ3D\nDd4N+A4TDi4OSQ5kDn8Omw62DtIO7g8JDyUPQQ9eD3oPlg+zD88P7BAJECYQQxBhEH4QmxC5ENcQ9RET\nETERTxFtEYwRqhHJEegSBxImEkUSZBKEEqMSwxLjEwMTIxNDE2MTgxOkE8UT5RQGFCcUSRRqFIsUrRTO\nFPAVEhU0FVYVeBWbFb0V4BYDFiYWSRZsFo8WshbWFvoXHRdBF2UXiReuF9IX9xgbGEAYZRiKGK8Y1Rj6\nGSAZRRlrGZEZtxndGgQaKhpRGncanhrFGuwbFBs7G2MbihuyG9ocAhwqHFIcexyjHMwc9R0eHUcdcB2Z\nHcMd7B4WHkAeah6UHr4e6R8THz4faR+UH78f6iAVIEEgbCCYIMQg8CEcIUghdSGhIc4h+yInIlUigiKv\nIt0jCiM4I2YjlCPCI/AkHyRNJHwkqyTaJQklOCVoJZclxyX3JicmVyaHJrcm6CcYJ0kneierJ9woDSg/\nKHEooijUKQYpOClrKZ0p0CoCKjUqaCqbKs8rAis2K2krnSvRLAUsOSxuLKIs1y0MLUEtdi2rLeEuFi5M\nLoIuty7uLyQvWi+RL8cv/jA1MGwwpDDbMRIxSjGCMbox8jIqMmMymzLUMw0zRjN/M7gz8TQrNGU0njTY\nNRM1TTWHNcI1/TY3NnI2rjbpNyQ3YDecN9c4FDhQOIw4yDkFOUI5fzm8Ofk6Njp0OrI67zstO2s7qjvo\nPCc8ZTykPOM9Ij1hPaE94D4gPmA+oD7gPyE/YT+iP+JAI0BkQKZA50EpQWpBrEHuQjBCckK1QvdDOkN9\nQ8BEA0RHRIpEzkUSRVVFmkXeRiJGZ0arRvBHNUd7R8BIBUhLSJFI10kdSWNJqUnwSjdKfUrESwxLU0ua\nS+JMKkxyTLpNAk1KTZNN3E4lTm5Ot08AT0lPk0/dUCdQcVC7UQZRUFGbUeZSMVJ8UsdTE1NfU6pT9lRC\nVI9U21UoVXVVwlYPVlxWqVb3V0RXklfgWC9YfVjLWRpZaVm4WgdaVlqmWvVbRVuVW+VcNVyGXNZdJ114\nXcleGl5sXr1fD19hX7NgBWBXYKpg/GFPYaJh9WJJYpxi8GNDY5dj62RAZJRk6WU9ZZJl52Y9ZpJm6Gc9\nZ5Nn6Wg/aJZo7GlDaZpp8WpIap9q92tPa6dr/2xXbK9tCG1gbbluEm5rbsRvHm94b9FwK3CGcOBxOnGV\ncfByS3KmcwFzXXO4dBR0cHTMdSh1hXXhdj52m3b4d1Z3s3gReG54zHkqeYl553pGeqV7BHtje8J8IXyB\nfOF9QX2hfgF+Yn7CfyN/hH/lgEeAqIEKgWuBzYIwgpKC9INXg7qEHYSAhOOFR4Wrhg6GcobXhzuHn4gE\niGmIzokziZmJ/opkisqLMIuWi/yMY4zKjTGNmI3/jmaOzo82j56QBpBukNaRP5GokhGSepLjk02TtpQg\nlIqU9JVflcmWNJaflwqXdZfgmEyYuJkkmZCZ/JpomtWbQpuvnByciZz3nWSd0p5Anq6fHZ+Ln/qgaaDY\noUehtqImopajBqN2o+akVqTHpTilqaYapoum/adup+CoUqjEqTepqaocqo+rAqt1q+msXKzQrUStuK4t\nrqGvFq+LsACwdbDqsWCx1rJLssKzOLOutCW0nLUTtYq2AbZ5tvC3aLfguFm40blKucK6O7q1uy67p7wh\nvJu9Fb2Pvgq+hL7/v3q/9cBwwOzBZ8Hjwl/C28NYw9TEUcTOxUvFyMZGxsPHQce/yD3IvMk6ybnKOMq3\nyzbLtsw1zLXNNc21zjbOts83z7jQOdC60TzRvtI/0sHTRNPG1EnUy9VO1dHWVdbY11zX4Nhk2OjZbNnx\n2nba+9uA3AXcit0Q3ZbeHN6i3ynfr+A24L3hROHM4lPi2+Nj4+vkc+T85YTmDeaW5x/nqegy6LzpRunQ\n6lvq5etw6/vshu0R7ZzuKO6070DvzPBY8OXxcvH/8ozzGfOn9DT0wvVQ9d72bfb794r4Gfio+Tj5x/pX\n+uf7d/wH/Jj9Kf26/kv+3P9t///SGw9AJaIjQoAFgA6ACdMPJygpRhSACIAPTxENck1NACoAAAAsAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABIBAAADAAAAAQADAAABAQADAAAAAQADAAAB\nAgADAAAABAAAARoBAwADAAAAAQABAAABBgADAAAAAQACAAABCgADAAAAAQABAAABEQAEAAAAAQAAAAgB\nEgADAAAAAQABAAABFQADAAAAAQAEAAABFgADAAAAAQADAAABFwAEAAAAAQAAACQBGgAFAAAAAQAAAQoB\nGwAFAAAAAQAAARIBHAADAAAAAQABAAABKAADAAAAAQACAAABUgADAAAAAQABAAABUwADAAAABAAAASKH\ncwAHAAAMSAAAASoAAAAAAAAA2AAAAAEAAADYAAAAAQAIAAgACAAIAAEAAQABAAEAAAxITGlubwIQAABt\nbnRyUkdCIFhZWiAHzgACAAkABgAxAABhY3NwTVNGVAAAAABJRUMgc1JHQgAAAAAAAAAAAAAAAAAA9tYA\nAQAAAADTLUhQICAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABFj\ncHJ0AAABUAAAADNkZXNjAAABhAAAAGx3dHB0AAAB8AAAABRia3B0AAACBAAAABRyWFlaAAACGAAAABRn\nWFlaAAACLAAAABRiWFlaAAACQAAAABRkbW5kAAACVAAAAHBkbWRkAAACxAAAAIh2dWVkAAADTAAAAIZ2\naWV3AAAD1AAAACRsdW1pAAAD+AAAABRtZWFzAAAEDAAAACR0ZWNoAAAEMAAAAAxyVFJDAAAEPAAACAxn\nVFJDAAAEPAAACAxiVFJDAAAEPAAACAx0ZXh0AAAAAENvcHlyaWdodCAoYykgMTk5OCBIZXdsZXR0LVBh\nY2thcmQgQ29tcGFueQAAZGVzYwAAAAAAAAASc1JHQiBJRUM2MTk2Ni0yLjEAAAAAAAAAAAAAABJzUkdC\nIElFQzYxOTY2LTIuMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAWFlaIAAAAAAAAPNRAAEAAAABFsxYWVogAAAAAAAAAAAAAAAAAAAAAFhZWiAAAAAAAABvogAAOPUA\nAAOQWFlaIAAAAAAAAGKZAAC3hQAAGNpYWVogAAAAAAAAJKAAAA+EAAC2z2Rlc2MAAAAAAAAAFklFQyBo\ndHRwOi8vd3d3LmllYy5jaAAAAAAAAAAAAAAAFklFQyBodHRwOi8vd3d3LmllYy5jaAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABkZXNjAAAAAAAAAC5JRUMgNjE5NjYtMi4x\nIERlZmF1bHQgUkdCIGNvbG91ciBzcGFjZSAtIHNSR0IAAAAAAAAAAAAAAC5JRUMgNjE5NjYtMi4xIERl\nZmF1bHQgUkdCIGNvbG91ciBzcGFjZSAtIHNSR0IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZGVzYwAAAAAA\nAAAsUmVmZXJlbmNlIFZpZXdpbmcgQ29uZGl0aW9uIGluIElFQzYxOTY2LTIuMQAAAAAAAAAAAAAALFJl\nZmVyZW5jZSBWaWV3aW5nIENvbmRpdGlvbiBpbiBJRUM2MTk2Ni0yLjEAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAHZpZXcAAAAAABOk/gAUXy4AEM8UAAPtzAAEEwsAA1yeAAAAAVhZWiAAAAAAAEwJVgBQAAAA\nVx/nbWVhcwAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAo8AAAACc2lnIAAAAABDUlQgY3VydgAAAAAA\nAAQAAAAABQAKAA8AFAAZAB4AIwAoAC0AMgA3ADsAQABFAEoATwBUAFkAXgBjAGgAbQByAHcAfACBAIYA\niwCQAJUAmgCfAKQAqQCuALIAtwC8AMEAxgDLANAA1QDbAOAA5QDrAPAA9gD7AQEBBwENARMBGQEfASUB\nKwEyATgBPgFFAUwBUgFZAWABZwFuAXUBfAGDAYsBkgGaAaEBqQGxAbkBwQHJAdEB2QHhAekB8gH6AgMC\nDAIUAh0CJgIvAjgCQQJLAlQCXQJnAnECegKEAo4CmAKiAqwCtgLBAssC1QLgAusC9QMAAwsDFgMhAy0D\nOANDA08DWgNmA3IDfgOKA5YDogOuA7oDxwPTA+AD7AP5BAYEEwQgBC0EOwRIBFUEYwRxBH4EjASaBKgE\ntgTEBNME4QTwBP4FDQUcBSsFOgVJBVgFZwV3BYYFlgWmBbUFxQXVBeUF9gYGBhYGJwY3BkgGWQZqBnsG\njAadBq8GwAbRBuMG9QcHBxkHKwc9B08HYQd0B4YHmQesB78H0gflB/gICwgfCDIIRghaCG4IggiWCKoI\nvgjSCOcI+wkQCSUJOglPCWQJeQmPCaQJugnPCeUJ+woRCicKPQpUCmoKgQqYCq4KxQrcCvMLCwsiCzkL\nUQtpC4ALmAuwC8gL4Qv5DBIMKgxDDFwMdQyODKcMwAzZDPMNDQ0mDUANWg10DY4NqQ3DDd4N+A4TDi4O\nSQ5kDn8Omw62DtIO7g8JDyUPQQ9eD3oPlg+zD88P7BAJECYQQxBhEH4QmxC5ENcQ9RETETERTxFtEYwR\nqhHJEegSBxImEkUSZBKEEqMSwxLjEwMTIxNDE2MTgxOkE8UT5RQGFCcUSRRqFIsUrRTOFPAVEhU0FVYV\neBWbFb0V4BYDFiYWSRZsFo8WshbWFvoXHRdBF2UXiReuF9IX9xgbGEAYZRiKGK8Y1Rj6GSAZRRlrGZEZ\ntxndGgQaKhpRGncanhrFGuwbFBs7G2MbihuyG9ocAhwqHFIcexyjHMwc9R0eHUcdcB2ZHcMd7B4WHkAe\nah6UHr4e6R8THz4faR+UH78f6iAVIEEgbCCYIMQg8CEcIUghdSGhIc4h+yInIlUigiKvIt0jCiM4I2Yj\nlCPCI/AkHyRNJHwkqyTaJQklOCVoJZclxyX3JicmVyaHJrcm6CcYJ0kneierJ9woDSg/KHEooijUKQYp\nOClrKZ0p0CoCKjUqaCqbKs8rAis2K2krnSvRLAUsOSxuLKIs1y0MLUEtdi2rLeEuFi5MLoIuty7uLyQv\nWi+RL8cv/jA1MGwwpDDbMRIxSjGCMbox8jIqMmMymzLUMw0zRjN/M7gz8TQrNGU0njTYNRM1TTWHNcI1\n/TY3NnI2rjbpNyQ3YDecN9c4FDhQOIw4yDkFOUI5fzm8Ofk6Njp0OrI67zstO2s7qjvoPCc8ZTykPOM9\nIj1hPaE94D4gPmA+oD7gPyE/YT+iP+JAI0BkQKZA50EpQWpBrEHuQjBCckK1QvdDOkN9Q8BEA0RHRIpE\nzkUSRVVFmkXeRiJGZ0arRvBHNUd7R8BIBUhLSJFI10kdSWNJqUnwSjdKfUrESwxLU0uaS+JMKkxyTLpN\nAk1KTZNN3E4lTm5Ot08AT0lPk0/dUCdQcVC7UQZRUFGbUeZSMVJ8UsdTE1NfU6pT9lRCVI9U21UoVXVV\nwlYPVlxWqVb3V0RXklfgWC9YfVjLWRpZaVm4WgdaVlqmWvVbRVuVW+VcNVyGXNZdJ114XcleGl5sXr1f\nD19hX7NgBWBXYKpg/GFPYaJh9WJJYpxi8GNDY5dj62RAZJRk6WU9ZZJl52Y9ZpJm6Gc9Z5Nn6Wg/aJZo\n7GlDaZpp8WpIap9q92tPa6dr/2xXbK9tCG1gbbluEm5rbsRvHm94b9FwK3CGcOBxOnGVcfByS3KmcwFz\nXXO4dBR0cHTMdSh1hXXhdj52m3b4d1Z3s3gReG54zHkqeYl553pGeqV7BHtje8J8IXyBfOF9QX2hfgF+\nYn7CfyN/hH/lgEeAqIEKgWuBzYIwgpKC9INXg7qEHYSAhOOFR4Wrhg6GcobXhzuHn4gEiGmIzokziZmJ\n/opkisqLMIuWi/yMY4zKjTGNmI3/jmaOzo82j56QBpBukNaRP5GokhGSepLjk02TtpQglIqU9JVflcmW\nNJaflwqXdZfgmEyYuJkkmZCZ/JpomtWbQpuvnByciZz3nWSd0p5Anq6fHZ+Ln/qgaaDYoUehtqImopaj\nBqN2o+akVqTHpTilqaYapoum/adup+CoUqjEqTepqaocqo+rAqt1q+msXKzQrUStuK4trqGvFq+LsACw\ndbDqsWCx1rJLssKzOLOutCW0nLUTtYq2AbZ5tvC3aLfguFm40blKucK6O7q1uy67p7whvJu9Fb2Pvgq+\nhL7/v3q/9cBwwOzBZ8Hjwl/C28NYw9TEUcTOxUvFyMZGxsPHQce/yD3IvMk6ybnKOMq3yzbLtsw1zLXN\nNc21zjbOts83z7jQOdC60TzRvtI/0sHTRNPG1EnUy9VO1dHWVdbY11zX4Nhk2OjZbNnx2nba+9uA3AXc\nit0Q3ZbeHN6i3ynfr+A24L3hROHM4lPi2+Nj4+vkc+T85YTmDeaW5x/nqegy6LzpRunQ6lvq5etw6/vs\nhu0R7ZzuKO6070DvzPBY8OXxcvH/8ozzGfOn9DT0wvVQ9d72bfb794r4Gfio+Tj5x/pX+uf7d/wH/Jj9\nKf26/kv+3P9t///SLS5JSl5OU011dGFibGVBcnJheaNJNDLVTE1OTw9QUVJTVFdOU1doaXRlXE5TQ29t\ncG9uZW50c1xOU0NvbG9yU3BhY2VfEBJOU0N1c3RvbUNvbG9yU3BhY2VEMCAwAEMwIDAQA4ASgBXUVldY\nD1laW1xUTlNJRFVOU0lDQ1dOU01vZGVsEAmAExAAgBRPERGcAAARnGFwcGwCAAAAbW50ckdSQVlYWVog\nB9wACAAXAA8ALgAPYWNzcEFQUEwAAAAAbm9uZQAAAAAAAAAAAAAAAAAAAAAAAPbWAAEAAAAA0y1hcHBs\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFZGVzYwAAAMAAAAB5\nZHNjbQAAATwAAAgaY3BydAAACVgAAAAjd3RwdAAACXwAAAAUa1RSQwAACZAAAAgMZGVzYwAAAAAAAAAf\nR2VuZXJpYyBHcmF5IEdhbW1hIDIuMiBQcm9maWxlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1sdWMAAAAA\nAAAAHwAAAAxza1NLAAAALgAAAYRkYURLAAAAOgAAAbJjYUVTAAAAOAAAAex2aVZOAAAAQAAAAiRwdEJS\nAAAASgAAAmR1a1VBAAAALAAAAq5mckZVAAAAPgAAAtpodUhVAAAANAAAAxh6aFRXAAAAGgAAA0xrb0tS\nAAAAIgAAA2ZuYk5PAAAAOgAAA4hjc0NaAAAAKAAAA8JoZUlMAAAAJAAAA+pyb1JPAAAAKgAABA5kZURF\nAAAATgAABDhpdElUAAAATgAABIZzdlNFAAAAOAAABNR6aENOAAAAGgAABQxqYUpQAAAAJgAABSZlbEdS\nAAAAKgAABUxwdFBPAAAAUgAABXZubE5MAAAAQAAABchlc0VTAAAATAAABgh0aFRIAAAAMgAABlR0clRS\nAAAAJAAABoZmaUZJAAAARgAABqpockhSAAAAPgAABvBwbFBMAAAASgAABy5hckVHAAAALAAAB3hydVJV\nAAAAOgAAB6RlblVTAAAAPAAAB94AVgFhAGUAbwBiAGUAYwBuAOEAIABzAGkAdgDhACAAZwBhAG0AYQAg\nADIALAAyAEcAZQBuAGUAcgBpAHMAawAgAGcAcgDlACAAMgAsADIAIABnAGEAbQBtAGEALQBwAHIAbwBm\nAGkAbABHAGEAbQBtAGEAIABkAGUAIABnAHIAaQBzAG8AcwAgAGcAZQBuAOgAcgBpAGMAYQAgADIALgAy\nAEMepQB1ACAAaADsAG4AaAAgAE0A4AB1ACAAeADhAG0AIABDAGgAdQBuAGcAIABHAGEAbQBtAGEAIAAy\nAC4AMgBQAGUAcgBmAGkAbAAgAEcAZQBuAOkAcgBpAGMAbwAgAGQAYQAgAEcAYQBtAGEAIABkAGUAIABD\nAGkAbgB6AGEAcwAgADIALAAyBBcEMAQzBDAEOwRMBD0EMAAgAEcAcgBhAHkALQQzBDAEPAQwACAAMgAu\nADIAUAByAG8AZgBpAGwAIABnAOkAbgDpAHIAaQBxAHUAZQAgAGcAcgBpAHMAIABnAGEAbQBtAGEAIAAy\nACwAMgDBAGwAdABhAGwA4QBuAG8AcwAgAHMAegD8AHIAawBlACAAZwBhAG0AbQBhACAAMgAuADKQGnUo\ncHCWjlFJXqYAMgAuADKCcl9pY8+P8Md8vBgAINaMwMkAIKwQucgAIAAyAC4AMgAg1QS4XNMMx3wARwBl\nAG4AZQByAGkAcwBrACAAZwByAOUAIABnAGEAbQBtAGEAIAAyACwAMgAtAHAAcgBvAGYAaQBsAE8AYgBl\nAGMAbgDhACABYQBlAGQA4QAgAGcAYQBtAGEAIAAyAC4AMgXSBdAF3gXUACAF0AXkBdUF6AAgBdsF3AXc\nBdkAIAAyAC4AMgBHAGEAbQBhACAAZwByAGkAIABnAGUAbgBlAHIAaQBjAQMAIAAyACwAMgBBAGwAbABn\nAGUAbQBlAGkAbgBlAHMAIABHAHIAYQB1AHMAdAB1AGYAZQBuAC0AUAByAG8AZgBpAGwAIABHAGEAbQBt\nAGEAIAAyACwAMgBQAHIAbwBmAGkAbABvACAAZwByAGkAZwBpAG8AIABnAGUAbgBlAHIAaQBjAG8AIABk\nAGUAbABsAGEAIABnAGEAbQBtAGEAIAAyACwAMgBHAGUAbgBlAHIAaQBzAGsAIABnAHIA5QAgADIALAAy\nACAAZwBhAG0AbQBhAHAAcgBvAGYAaQBsZm6QGnBwXqZ8+2VwADIALgAyY8+P8GWHTvZOAIIsMLAw7DCk\nMKww8zDeACAAMgAuADIAIDDXMO0w1TChMKQw6wOTA7UDvQO5A7oDzAAgA5MDugPBA7kAIAOTA6wDvAO8\nA7EAIAAyAC4AMgBQAGUAcgBmAGkAbAAgAGcAZQBuAOkAcgBpAGMAbwAgAGQAZQAgAGMAaQBuAHoAZQBu\nAHQAbwBzACAAZABhACAARwBhAG0AbQBhACAAMgAsADIAQQBsAGcAZQBtAGUAZQBuACAAZwByAGkAagBz\nACAAZwBhAG0AbQBhACAAMgAsADIALQBwAHIAbwBmAGkAZQBsAFAAZQByAGYAaQBsACAAZwBlAG4A6QBy\nAGkAYwBvACAAZABlACAAZwBhAG0AbQBhACAAZABlACAAZwByAGkAcwBlAHMAIAAyACwAMg4jDjEOBw4q\nDjUOQQ4BDiEOIQ4yDkAOAQ4jDiIOTA4XDjEOSA4nDkQOGwAgADIALgAyAEcAZQBuAGUAbAAgAEcAcgBp\nACAARwBhAG0AYQAgADIALAAyAFkAbABlAGkAbgBlAG4AIABoAGEAcgBtAGEAYQBuACAAZwBhAG0AbQBh\nACAAMgAsADIAIAAtAHAAcgBvAGYAaQBpAGwAaQBHAGUAbgBlAHIAaQENAGsAaQAgAEcAcgBhAHkAIABH\nAGEAbQBtAGEAIAAyAC4AMgAgAHAAcgBvAGYAaQBsAFUAbgBpAHcAZQByAHMAYQBsAG4AeQAgAHAAcgBv\nAGYAaQBsACAAcwB6AGEAcgBvAVsAYwBpACAAZwBhAG0AbQBhACAAMgAsADIGOgYnBkUGJwAgADIALgAy\nACAGRAZIBkYAIAYxBkUGJwYvBkoAIAY5BicGRQQeBDEESQQwBE8AIARBBDUEQAQwBE8AIAQzBDAEPAQ8\nBDAAIAAyACwAMgAtBD8EQAQ+BEQEOAQ7BEwARwBlAG4AZQByAGkAYwAgAEcAcgBhAHkAIABHAGEAbQBt\nAGEAIAAyAC4AMgAgAFAAcgBvAGYAaQBsAGUAAHRleHQAAAAAQ29weXJpZ2h0IEFwcGxlIEluYy4sIDIw\nMTIAAFhZWiAAAAAAAADzUQABAAAAARbMY3VydgAAAAAAAAQAAAAABQAKAA8AFAAZAB4AIwAoAC0AMgA3\nADsAQABFAEoATwBUAFkAXgBjAGgAbQByAHcAfACBAIYAiwCQAJUAmgCfAKQAqQCuALIAtwC8AMEAxgDL\nANAA1QDbAOAA5QDrAPAA9gD7AQEBBwENARMBGQEfASUBKwEyATgBPgFFAUwBUgFZAWABZwFuAXUBfAGD\nAYsBkgGaAaEBqQGxAbkBwQHJAdEB2QHhAekB8gH6AgMCDAIUAh0CJgIvAjgCQQJLAlQCXQJnAnECegKE\nAo4CmAKiAqwCtgLBAssC1QLgAusC9QMAAwsDFgMhAy0DOANDA08DWgNmA3IDfgOKA5YDogOuA7oDxwPT\nA+AD7AP5BAYEEwQgBC0EOwRIBFUEYwRxBH4EjASaBKgEtgTEBNME4QTwBP4FDQUcBSsFOgVJBVgFZwV3\nBYYFlgWmBbUFxQXVBeUF9gYGBhYGJwY3BkgGWQZqBnsGjAadBq8GwAbRBuMG9QcHBxkHKwc9B08HYQd0\nB4YHmQesB78H0gflB/gICwgfCDIIRghaCG4IggiWCKoIvgjSCOcI+wkQCSUJOglPCWQJeQmPCaQJugnP\nCeUJ+woRCicKPQpUCmoKgQqYCq4KxQrcCvMLCwsiCzkLUQtpC4ALmAuwC8gL4Qv5DBIMKgxDDFwMdQyO\nDKcMwAzZDPMNDQ0mDUANWg10DY4NqQ3DDd4N+A4TDi4OSQ5kDn8Omw62DtIO7g8JDyUPQQ9eD3oPlg+z\nD88P7BAJECYQQxBhEH4QmxC5ENcQ9RETETERTxFtEYwRqhHJEegSBxImEkUSZBKEEqMSwxLjEwMTIxND\nE2MTgxOkE8UT5RQGFCcUSRRqFIsUrRTOFPAVEhU0FVYVeBWbFb0V4BYDFiYWSRZsFo8WshbWFvoXHRdB\nF2UXiReuF9IX9xgbGEAYZRiKGK8Y1Rj6GSAZRRlrGZEZtxndGgQaKhpRGncanhrFGuwbFBs7G2Mbihuy\nG9ocAhwqHFIcexyjHMwc9R0eHUcdcB2ZHcMd7B4WHkAeah6UHr4e6R8THz4faR+UH78f6iAVIEEgbCCY\nIMQg8CEcIUghdSGhIc4h+yInIlUigiKvIt0jCiM4I2YjlCPCI/AkHyRNJHwkqyTaJQklOCVoJZclxyX3\nJicmVyaHJrcm6CcYJ0kneierJ9woDSg/KHEooijUKQYpOClrKZ0p0CoCKjUqaCqbKs8rAis2K2krnSvR\nLAUsOSxuLKIs1y0MLUEtdi2rLeEuFi5MLoIuty7uLyQvWi+RL8cv/jA1MGwwpDDbMRIxSjGCMbox8jIq\nMmMymzLUMw0zRjN/M7gz8TQrNGU0njTYNRM1TTWHNcI1/TY3NnI2rjbpNyQ3YDecN9c4FDhQOIw4yDkF\nOUI5fzm8Ofk6Njp0OrI67zstO2s7qjvoPCc8ZTykPOM9Ij1hPaE94D4gPmA+oD7gPyE/YT+iP+JAI0Bk\nQKZA50EpQWpBrEHuQjBCckK1QvdDOkN9Q8BEA0RHRIpEzkUSRVVFmkXeRiJGZ0arRvBHNUd7R8BIBUhL\nSJFI10kdSWNJqUnwSjdKfUrESwxLU0uaS+JMKkxyTLpNAk1KTZNN3E4lTm5Ot08AT0lPk0/dUCdQcVC7\nUQZRUFGbUeZSMVJ8UsdTE1NfU6pT9lRCVI9U21UoVXVVwlYPVlxWqVb3V0RXklfgWC9YfVjLWRpZaVm4\nWgdaVlqmWvVbRVuVW+VcNVyGXNZdJ114XcleGl5sXr1fD19hX7NgBWBXYKpg/GFPYaJh9WJJYpxi8GND\nY5dj62RAZJRk6WU9ZZJl52Y9ZpJm6Gc9Z5Nn6Wg/aJZo7GlDaZpp8WpIap9q92tPa6dr/2xXbK9tCG1g\nbbluEm5rbsRvHm94b9FwK3CGcOBxOnGVcfByS3KmcwFzXXO4dBR0cHTMdSh1hXXhdj52m3b4d1Z3s3gR\neG54zHkqeYl553pGeqV7BHtje8J8IXyBfOF9QX2hfgF+Yn7CfyN/hH/lgEeAqIEKgWuBzYIwgpKC9INX\ng7qEHYSAhOOFR4Wrhg6GcobXhzuHn4gEiGmIzokziZmJ/opkisqLMIuWi/yMY4zKjTGNmI3/jmaOzo82\nj56QBpBukNaRP5GokhGSepLjk02TtpQglIqU9JVflcmWNJaflwqXdZfgmEyYuJkkmZCZ/JpomtWbQpuv\nnByciZz3nWSd0p5Anq6fHZ+Ln/qgaaDYoUehtqImopajBqN2o+akVqTHpTilqaYapoum/adup+CoUqjE\nqTepqaocqo+rAqt1q+msXKzQrUStuK4trqGvFq+LsACwdbDqsWCx1rJLssKzOLOutCW0nLUTtYq2AbZ5\ntvC3aLfguFm40blKucK6O7q1uy67p7whvJu9Fb2Pvgq+hL7/v3q/9cBwwOzBZ8Hjwl/C28NYw9TEUcTO\nxUvFyMZGxsPHQce/yD3IvMk6ybnKOMq3yzbLtsw1zLXNNc21zjbOts83z7jQOdC60TzRvtI/0sHTRNPG\n1EnUy9VO1dHWVdbY11zX4Nhk2OjZbNnx2nba+9uA3AXcit0Q3ZbeHN6i3ynfr+A24L3hROHM4lPi2+Nj\n4+vkc+T85YTmDeaW5x/nqegy6LzpRunQ6lvq5etw6/vshu0R7ZzuKO6070DvzPBY8OXxcvH/8ozzGfOn\n9DT0wvVQ9d72bfb794r4Gfio+Tj5x/pX+uf7d/wH/Jj9Kf26/kv+3P9t///SLS5fYFxOU0NvbG9yU3Bh\nY2WiYTJcTlNDb2xvclNwYWNl0i0uY2RXTlNDb2xvcqJjMtItLmZnV05TSW1hZ2WiZjIACAARABoAJAAp\nADIANwBJAEwAUQBTAG0AcwCAAIcAlgCdAKoAsQC5ALsAvQC/AMQAxgDIAM8A1ADfAOMA5QDnAOkA6wDw\nAPMA9QD3APkBAAEXATMBNQE3DmUOag51Dn4OkQ6VDqAOqQ6uDrYOuQ6+DsEOww7FDscOzg7QDtIcNBw5\nHDwcPhxAHEIcSRxLHE0pwynIKdcp2ynmKe4p+yoIKh0qIiomKigqKiosKjUqOipAKkgqSipMKk4qUDvw\nO/U8AjwFPBI8FzwfPCI8JzwvAAAAAAAAAgEAAAAAAAAAaAAAAAAAAAAAAAAAAAAAPDI\n</mutableData>\n        </image>\n    </resources>\n</document>\n"
  },
  {
    "path": "Resources/MainUI/First time setup/WelcomeViewController.swift",
    "content": "//\n//  WelcomeViewController.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 29/07/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Cocoa\n\nclass WelcomeViewController: NSViewController {\n    @IBOutlet var bigTitle: NSTextField!\n    @IBOutlet var textBelow: NSTextField!\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n        // Do view setup here.\n        if PrefsVideos.videoFormat != .v1080pH264 {\n            bigTitle.stringValue = \"Welcome back to Aerial\"\n            textBelow.stringValue = \"We've changed a thing or two, so let's go over that!\"\n        }\n    }\n\n}\n"
  },
  {
    "path": "Resources/MainUI/First time setup/WelcomeViewController.xib",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.Cocoa.XIB\" version=\"3.0\" toolsVersion=\"19529\" targetRuntime=\"MacOSX.Cocoa\" propertyAccessControl=\"none\" useAutolayout=\"YES\" customObjectInstantitationMethod=\"direct\">\n    <dependencies>\n        <deployment identifier=\"macosx\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.CocoaPlugin\" version=\"19529\"/>\n        <capability name=\"documents saved in the Xcode 8 format\" minToolsVersion=\"8.0\"/>\n    </dependencies>\n    <objects>\n        <customObject id=\"-2\" userLabel=\"File's Owner\" customClass=\"WelcomeViewController\" customModule=\"Aerial\" customModuleProvider=\"target\">\n            <connections>\n                <outlet property=\"bigTitle\" destination=\"3Ht-yo-ckm\" id=\"eVi-Sx-RcC\"/>\n                <outlet property=\"textBelow\" destination=\"AiK-TD-2Qt\" id=\"Xon-55-eXK\"/>\n                <outlet property=\"view\" destination=\"Hz6-mo-xeY\" id=\"0bl-1N-x8E\"/>\n            </connections>\n        </customObject>\n        <customObject id=\"-1\" userLabel=\"First Responder\" customClass=\"FirstResponder\"/>\n        <customObject id=\"-3\" userLabel=\"Application\" customClass=\"NSObject\"/>\n        <customView id=\"Hz6-mo-xeY\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"800\" height=\"600\"/>\n            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n            <subviews>\n                <box boxType=\"custom\" borderType=\"none\" cornerRadius=\"4\" title=\"Box\" titlePosition=\"noTitle\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"eVB-C0-e5X\">\n                    <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"800\" height=\"600\"/>\n                    <view key=\"contentView\" ambiguous=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"klP-MJ-bdd\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"800\" height=\"600\"/>\n                        <subviews>\n                            <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"AiK-TD-2Qt\">\n                                <rect key=\"frame\" x=\"408\" y=\"283\" width=\"313\" height=\"34\"/>\n                                <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" id=\"Uez-be-ewR\">\n                                    <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                    <string key=\"title\">Just a couple questions to adjust your settings, \nit will be quick!</string>\n                                    <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                </textFieldCell>\n                            </textField>\n                            <imageView horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"8XI-B4-VMv\">\n                                <rect key=\"frame\" x=\"50\" y=\"140\" width=\"320\" height=\"320\"/>\n                                <constraints>\n                                    <constraint firstAttribute=\"height\" constant=\"320\" id=\"CDx-dH-VPg\"/>\n                                    <constraint firstAttribute=\"width\" constant=\"320\" id=\"Psv-Kd-WJ3\"/>\n                                </constraints>\n                                <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" image=\"icon-512\" id=\"2ck-4q-RCI\"/>\n                            </imageView>\n                            <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"3Ht-yo-ckm\">\n                                <rect key=\"frame\" x=\"408\" y=\"362\" width=\"336\" height=\"43\"/>\n                                <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"Welcome to Aerial 3\" id=\"zIs-lv-iOt\">\n                                    <font key=\"font\" metaFont=\"systemBold\" size=\"36\"/>\n                                    <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                </textFieldCell>\n                            </textField>\n                        </subviews>\n                        <constraints>\n                            <constraint firstItem=\"AiK-TD-2Qt\" firstAttribute=\"top\" secondItem=\"3Ht-yo-ckm\" secondAttribute=\"bottom\" constant=\"45\" id=\"1fX-AF-tm6\"/>\n                            <constraint firstItem=\"AiK-TD-2Qt\" firstAttribute=\"leading\" secondItem=\"8XI-B4-VMv\" secondAttribute=\"trailing\" constant=\"40\" id=\"C3Q-re-Cml\"/>\n                            <constraint firstItem=\"AiK-TD-2Qt\" firstAttribute=\"leading\" secondItem=\"3Ht-yo-ckm\" secondAttribute=\"leading\" id=\"FvT-4Y-TsK\"/>\n                            <constraint firstItem=\"8XI-B4-VMv\" firstAttribute=\"leading\" secondItem=\"klP-MJ-bdd\" secondAttribute=\"leading\" constant=\"50\" id=\"MWY-6A-waf\"/>\n                            <constraint firstItem=\"AiK-TD-2Qt\" firstAttribute=\"centerY\" secondItem=\"8XI-B4-VMv\" secondAttribute=\"centerY\" id=\"nwE-R8-59k\"/>\n                            <constraint firstItem=\"8XI-B4-VMv\" firstAttribute=\"top\" secondItem=\"klP-MJ-bdd\" secondAttribute=\"top\" constant=\"140\" id=\"shL-Ik-nPZ\"/>\n                            <constraint firstAttribute=\"bottom\" secondItem=\"8XI-B4-VMv\" secondAttribute=\"bottom\" constant=\"140\" id=\"ygI-A6-tmh\"/>\n                        </constraints>\n                    </view>\n                    <constraints>\n                        <constraint firstAttribute=\"height\" constant=\"600\" id=\"gvD-my-C0q\"/>\n                        <constraint firstAttribute=\"width\" constant=\"800\" id=\"qUw-Iy-I2s\"/>\n                    </constraints>\n                    <color key=\"fillColor\" name=\"windowBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                </box>\n            </subviews>\n            <constraints>\n                <constraint firstItem=\"eVB-C0-e5X\" firstAttribute=\"top\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"top\" id=\"ILN-w6-Tat\"/>\n                <constraint firstItem=\"eVB-C0-e5X\" firstAttribute=\"leading\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"leading\" id=\"RAC-tQ-WOy\"/>\n                <constraint firstAttribute=\"bottom\" secondItem=\"eVB-C0-e5X\" secondAttribute=\"bottom\" id=\"Rre-uU-kCL\"/>\n                <constraint firstAttribute=\"trailing\" secondItem=\"eVB-C0-e5X\" secondAttribute=\"trailing\" id=\"wXz-Pu-QKI\"/>\n            </constraints>\n            <point key=\"canvasLocation\" x=\"-58.5\" y=\"217\"/>\n        </customView>\n    </objects>\n    <resources>\n        <image name=\"icon-512\" width=\"512\" height=\"512\"/>\n    </resources>\n</document>\n"
  },
  {
    "path": "Resources/MainUI/Infos panels/CreditsViewController.swift",
    "content": "//\n//  CreditsViewController.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 25/07/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Cocoa\n\nclass CreditsViewController: NSViewController {\n\n    @IBOutlet var scrollView: NSScrollView!\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n        \n        scrollView.contentView.scroll(NSMakePoint(0,0))\n    }\n\n    @IBAction func translationButton(_ sender: Any) {\n        let workspace = NSWorkspace.shared\n        let url = URL(string: \"https://github.com/JohnCoates/Aerial/issues/792\")!\n        workspace.open(url)\n    }\n\n    @IBAction func websiteButton(_ sender: Any) {\n        let workspace = NSWorkspace.shared\n        let url = URL(string: \"https://aerialscreensaver.github.io\")!\n        workspace.open(url)\n    }\n\n    @IBAction func projectButton(_ sender: Any) {\n        let workspace = NSWorkspace.shared\n        let url = URL(string: \"https://github.com/JohnCoates/Aerial\")!\n        workspace.open(url)\n    }\n\n    @IBAction func discordButton(_ sender: Any) {\n        let workspace = NSWorkspace.shared\n        let url = URL(string: \"https://discord.gg/TPuA5WG\")!\n        workspace.open(url)\n    }\n}\n"
  },
  {
    "path": "Resources/MainUI/Infos panels/CreditsViewController.xib",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.Cocoa.XIB\" version=\"3.0\" toolsVersion=\"22113.1\" targetRuntime=\"MacOSX.Cocoa\" propertyAccessControl=\"none\" useAutolayout=\"YES\" customObjectInstantitationMethod=\"direct\">\n    <dependencies>\n        <deployment identifier=\"macosx\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.CocoaPlugin\" version=\"22113.1\"/>\n        <capability name=\"documents saved in the Xcode 8 format\" minToolsVersion=\"8.0\"/>\n    </dependencies>\n    <objects>\n        <customObject id=\"-2\" userLabel=\"File's Owner\" customClass=\"CreditsViewController\" customModule=\"Aerial\" customModuleProvider=\"target\">\n            <connections>\n                <outlet property=\"scrollView\" destination=\"JTK-WM-mgr\" id=\"dZt-no-pT9\"/>\n                <outlet property=\"view\" destination=\"Hz6-mo-xeY\" id=\"0bl-1N-x8E\"/>\n            </connections>\n        </customObject>\n        <customObject id=\"-1\" userLabel=\"First Responder\" customClass=\"FirstResponder\"/>\n        <customObject id=\"-3\" userLabel=\"Application\" customClass=\"NSObject\"/>\n        <customView translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Hz6-mo-xeY\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"811\" height=\"530\"/>\n            <subviews>\n                <scrollView horizontalLineScroll=\"10\" horizontalPageScroll=\"10\" verticalLineScroll=\"10\" verticalPageScroll=\"10\" usesPredominantAxisScrolling=\"NO\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"JTK-WM-mgr\">\n                    <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"811\" height=\"530\"/>\n                    <clipView key=\"contentView\" id=\"Sz1-o4-35Y\">\n                        <rect key=\"frame\" x=\"1\" y=\"1\" width=\"809\" height=\"528\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <subviews>\n                            <customView translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Y1q-aR-nvJ\">\n                                <rect key=\"frame\" x=\"0.0\" y=\"-2\" width=\"809\" height=\"530\"/>\n                                <subviews>\n                                    <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"751\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"ReU-xc-cMA\">\n                                        <rect key=\"frame\" x=\"198\" y=\"459\" width=\"504\" height=\"51\"/>\n                                        <constraints>\n                                            <constraint firstAttribute=\"width\" constant=\"500\" id=\"GtJ-bZ-C8o\"/>\n                                        </constraints>\n                                        <textFieldCell key=\"cell\" id=\"PfR-gx-qhk\">\n                                            <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                            <string key=\"title\">Aerial was started in 2015 by John Coates. \n\nSince version 1.4, Aerial is developed and maintained by Guillaume Louel.</string>\n                                            <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                            <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                        </textFieldCell>\n                                    </textField>\n                                    <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Gv6-y0-c1S\">\n                                        <rect key=\"frame\" x=\"194\" y=\"35\" width=\"135\" height=\"40\"/>\n                                        <buttonCell key=\"cell\" type=\"push\" title=\"Contact us here\" bezelStyle=\"rounded\" alignment=\"center\" controlSize=\"large\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"a1o-SL-FaN\">\n                                            <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                                            <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                        </buttonCell>\n                                        <connections>\n                                            <action selector=\"translationButton:\" target=\"-2\" id=\"7re-4c-oVR\"/>\n                                        </connections>\n                                    </button>\n                                    <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"hEl-hg-Xq5\">\n                                        <rect key=\"frame\" x=\"194\" y=\"405\" width=\"142\" height=\"40\"/>\n                                        <buttonCell key=\"cell\" type=\"push\" title=\"Visit our Website\" bezelStyle=\"rounded\" alignment=\"center\" controlSize=\"large\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"8Qc-M5-TLV\">\n                                            <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                                            <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                        </buttonCell>\n                                        <connections>\n                                            <action selector=\"websiteButton:\" target=\"-2\" id=\"LGP-oT-yPC\"/>\n                                        </connections>\n                                    </button>\n                                    <textField focusRingType=\"none\" verticalHuggingPriority=\"750\" horizontalCompressionResistancePriority=\"250\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"wpw-1v-dic\">\n                                        <rect key=\"frame\" x=\"198\" y=\"85\" width=\"311\" height=\"306\"/>\n                                        <textFieldCell key=\"cell\" selectable=\"YES\" id=\"sP2-o5-2MT\">\n                                            <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                            <string key=\"title\">Translations contributed by:\n- Arabic by Kachi Kulu\n- Dutch by Sebastiaan Speck\n- English by Sean M Smith\n- German by Matthias Bauer &amp; Thomas W.\n- Hebrew by Bry Jacks\n- Hungarian by Matt Crogan\n- Italian by Angelo Marguglio \n- Japanese by Junji 'Dr.MORO' Morokuma\n- Korean by Howon Kim\n- Polish by Aleksander Kasprzyk \n- Portuguese/Brazil by Renan Sigolo\n- Russian by Tema Sysoev and\n- Simplified &amp; Traditional Chinese by Linkey Leo\n- Spanish by Aitor García Rey \n- Swedish by Samuel Holm\n\nWant to help with translations?</string>\n                                            <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                            <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                        </textFieldCell>\n                                    </textField>\n                                    <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"2zM-0X-9R0\">\n                                        <rect key=\"frame\" x=\"363\" y=\"35\" width=\"133\" height=\"40\"/>\n                                        <buttonCell key=\"cell\" type=\"push\" title=\"Hop on Discord\" bezelStyle=\"rounded\" alignment=\"center\" controlSize=\"large\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"KmS-rN-Kxf\">\n                                            <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                                            <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                        </buttonCell>\n                                        <connections>\n                                            <action selector=\"discordButton:\" target=\"-2\" id=\"lkL-pw-NPM\"/>\n                                        </connections>\n                                    </button>\n                                    <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"ohW-uj-N2U\">\n                                        <rect key=\"frame\" x=\"337\" y=\"48\" width=\"18\" height=\"17\"/>\n                                        <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"or\" id=\"PRg-cf-Ee8\">\n                                            <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                            <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                            <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                        </textFieldCell>\n                                    </textField>\n                                    <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"J7J-2w-Ik9\">\n                                        <rect key=\"frame\" x=\"340\" y=\"405\" width=\"220\" height=\"40\"/>\n                                        <buttonCell key=\"cell\" type=\"push\" title=\"Visit the GitHub Project Page\" bezelStyle=\"rounded\" alignment=\"center\" controlSize=\"large\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"HmR-fK-HDO\">\n                                            <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                                            <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                        </buttonCell>\n                                        <connections>\n                                            <action selector=\"projectButton:\" target=\"-2\" id=\"Tcj-js-dfP\"/>\n                                        </connections>\n                                    </button>\n                                </subviews>\n                                <constraints>\n                                    <constraint firstItem=\"ReU-xc-cMA\" firstAttribute=\"top\" secondItem=\"Y1q-aR-nvJ\" secondAttribute=\"top\" constant=\"20\" id=\"0sG-76-mvU\"/>\n                                    <constraint firstItem=\"hEl-hg-Xq5\" firstAttribute=\"leading\" secondItem=\"ReU-xc-cMA\" secondAttribute=\"leading\" id=\"2a3-G4-3pv\"/>\n                                    <constraint firstItem=\"wpw-1v-dic\" firstAttribute=\"top\" secondItem=\"hEl-hg-Xq5\" secondAttribute=\"bottom\" constant=\"20\" id=\"72h-2j-fjF\"/>\n                                    <constraint firstItem=\"2zM-0X-9R0\" firstAttribute=\"leading\" secondItem=\"ohW-uj-N2U\" secondAttribute=\"trailing\" constant=\"16\" id=\"8ng-v3-ogZ\"/>\n                                    <constraint firstItem=\"ReU-xc-cMA\" firstAttribute=\"leading\" secondItem=\"Y1q-aR-nvJ\" secondAttribute=\"leading\" constant=\"200\" id=\"CyR-CF-1w9\"/>\n                                    <constraint firstItem=\"wpw-1v-dic\" firstAttribute=\"leading\" secondItem=\"hEl-hg-Xq5\" secondAttribute=\"leading\" id=\"EoY-Nm-Gma\"/>\n                                    <constraint firstItem=\"ohW-uj-N2U\" firstAttribute=\"leading\" secondItem=\"Gv6-y0-c1S\" secondAttribute=\"trailing\" constant=\"16\" id=\"GPY-ag-5sK\"/>\n                                    <constraint firstItem=\"ohW-uj-N2U\" firstAttribute=\"firstBaseline\" secondItem=\"Gv6-y0-c1S\" secondAttribute=\"firstBaseline\" id=\"Ufh-Mp-YbB\"/>\n                                    <constraint firstItem=\"2zM-0X-9R0\" firstAttribute=\"firstBaseline\" secondItem=\"Gv6-y0-c1S\" secondAttribute=\"firstBaseline\" id=\"UxQ-eg-aLW\"/>\n                                    <constraint firstItem=\"Gv6-y0-c1S\" firstAttribute=\"leading\" secondItem=\"wpw-1v-dic\" secondAttribute=\"leading\" id=\"eZZ-wK-odk\"/>\n                                    <constraint firstItem=\"J7J-2w-Ik9\" firstAttribute=\"firstBaseline\" secondItem=\"hEl-hg-Xq5\" secondAttribute=\"firstBaseline\" id=\"hIM-b9-aY1\"/>\n                                    <constraint firstAttribute=\"height\" constant=\"530\" id=\"j93-s5-71V\"/>\n                                    <constraint firstItem=\"J7J-2w-Ik9\" firstAttribute=\"leading\" secondItem=\"hEl-hg-Xq5\" secondAttribute=\"trailing\" constant=\"16\" id=\"m9w-Gb-5AR\"/>\n                                    <constraint firstItem=\"Gv6-y0-c1S\" firstAttribute=\"top\" secondItem=\"wpw-1v-dic\" secondAttribute=\"bottom\" constant=\"16\" id=\"nFt-Zo-mMV\"/>\n                                    <constraint firstItem=\"hEl-hg-Xq5\" firstAttribute=\"top\" secondItem=\"ReU-xc-cMA\" secondAttribute=\"bottom\" constant=\"20\" id=\"yh4-bS-5yh\"/>\n                                </constraints>\n                            </customView>\n                        </subviews>\n                        <constraints>\n                            <constraint firstItem=\"Y1q-aR-nvJ\" firstAttribute=\"leading\" secondItem=\"Sz1-o4-35Y\" secondAttribute=\"leading\" id=\"cO0-Nh-6hM\"/>\n                            <constraint firstAttribute=\"trailing\" secondItem=\"Y1q-aR-nvJ\" secondAttribute=\"trailing\" id=\"rpr-Mm-fcN\"/>\n                            <constraint firstItem=\"Y1q-aR-nvJ\" firstAttribute=\"top\" secondItem=\"Sz1-o4-35Y\" secondAttribute=\"top\" id=\"xrs-Vf-IF1\"/>\n                        </constraints>\n                    </clipView>\n                    <scroller key=\"horizontalScroller\" wantsLayer=\"YES\" verticalHuggingPriority=\"750\" horizontal=\"YES\" id=\"uxu-lf-jvj\">\n                        <rect key=\"frame\" x=\"1\" y=\"513\" width=\"809\" height=\"16\"/>\n                        <autoresizingMask key=\"autoresizingMask\"/>\n                    </scroller>\n                    <scroller key=\"verticalScroller\" wantsLayer=\"YES\" verticalHuggingPriority=\"750\" horizontal=\"NO\" id=\"34h-Lz-aVs\">\n                        <rect key=\"frame\" x=\"794\" y=\"1\" width=\"16\" height=\"528\"/>\n                        <autoresizingMask key=\"autoresizingMask\"/>\n                    </scroller>\n                </scrollView>\n            </subviews>\n            <constraints>\n                <constraint firstAttribute=\"bottom\" secondItem=\"JTK-WM-mgr\" secondAttribute=\"bottom\" id=\"4Uo-Sh-hPI\"/>\n                <constraint firstItem=\"JTK-WM-mgr\" firstAttribute=\"leading\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"leading\" id=\"CfZ-E8-gg4\"/>\n                <constraint firstAttribute=\"width\" relation=\"greaterThanOrEqual\" constant=\"811\" id=\"SVE-Ie-5qf\"/>\n                <constraint firstItem=\"JTK-WM-mgr\" firstAttribute=\"top\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"top\" id=\"j0S-Qf-RMg\"/>\n                <constraint firstAttribute=\"trailing\" secondItem=\"JTK-WM-mgr\" secondAttribute=\"trailing\" id=\"jCc-Px-UYb\"/>\n                <constraint firstAttribute=\"height\" relation=\"greaterThanOrEqual\" constant=\"530\" id=\"xcR-Bc-mK8\"/>\n            </constraints>\n            <point key=\"canvasLocation\" x=\"29.5\" y=\"150\"/>\n        </customView>\n    </objects>\n</document>\n"
  },
  {
    "path": "Resources/MainUI/Infos panels/HelpViewController.swift",
    "content": "//\n//  HelpViewController.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 25/07/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Cocoa\n\nclass HelpViewController: NSViewController {\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n        // Do view setup here.\n    }\n\n    @IBAction func faqButton(_ sender: Any) {\n        let workspace = NSWorkspace.shared\n        let url = URL(string: \"https://aerialscreensaver.github.io/faq.html\")!\n        workspace.open(url)\n    }\n\n    @IBAction func troubleshootButton(_ sender: Any) {\n        let workspace = NSWorkspace.shared\n        let url = URL(string: \"https://aerialscreensaver.github.io/troubleshooting.html\")!\n        workspace.open(url)\n    }\n\n    @IBAction func issuesButton(_ sender: Any) {\n        let workspace = NSWorkspace.shared\n        let url = URL(string: \"https://github.com/JohnCoates/Aerial/issues\")!\n        workspace.open(url)\n    }\n\n    @IBAction func visitDiscordClick(_ sender: Any) {\n        let workspace = NSWorkspace.shared\n        let url = URL(string: \"https://discord.gg/TPuA5WG\")!\n        workspace.open(url)\n    }\n\n}\n"
  },
  {
    "path": "Resources/MainUI/Infos panels/HelpViewController.xib",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.Cocoa.XIB\" version=\"3.0\" toolsVersion=\"22113.1\" targetRuntime=\"MacOSX.Cocoa\" propertyAccessControl=\"none\" useAutolayout=\"YES\" customObjectInstantitationMethod=\"direct\">\n    <dependencies>\n        <deployment identifier=\"macosx\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.CocoaPlugin\" version=\"22113.1\"/>\n        <capability name=\"documents saved in the Xcode 8 format\" minToolsVersion=\"8.0\"/>\n    </dependencies>\n    <objects>\n        <customObject id=\"-2\" userLabel=\"File's Owner\" customClass=\"HelpViewController\" customModule=\"Aerial\" customModuleProvider=\"target\">\n            <connections>\n                <outlet property=\"view\" destination=\"Hz6-mo-xeY\" id=\"0bl-1N-x8E\"/>\n            </connections>\n        </customObject>\n        <customObject id=\"-1\" userLabel=\"First Responder\" customClass=\"FirstResponder\"/>\n        <customObject id=\"-3\" userLabel=\"Application\" customClass=\"NSObject\"/>\n        <customView translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Hz6-mo-xeY\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"811\" height=\"530\"/>\n            <subviews>\n                <textField focusRingType=\"none\" verticalHuggingPriority=\"750\" horizontalCompressionResistancePriority=\"250\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"fiN-Oe-faj\">\n                    <rect key=\"frame\" x=\"198\" y=\"473\" width=\"84\" height=\"17\"/>\n                    <textFieldCell key=\"cell\" selectable=\"YES\" title=\"Need help? \" id=\"T0H-fO-TBy\">\n                        <font key=\"font\" metaFont=\"systemSemibold\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"UUX-vU-Iz9\">\n                    <rect key=\"frame\" x=\"194\" y=\"288\" width=\"229\" height=\"40\"/>\n                    <buttonCell key=\"cell\" type=\"push\" title=\"Check the Troubleshooting list\" bezelStyle=\"rounded\" alignment=\"center\" controlSize=\"large\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"sY3-LA-jwX\">\n                        <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"troubleshootButton:\" target=\"-2\" id=\"sxo-rj-tti\"/>\n                    </connections>\n                </button>\n                <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Ccg-Ld-deT\">\n                    <rect key=\"frame\" x=\"194\" y=\"173\" width=\"191\" height=\"40\"/>\n                    <buttonCell key=\"cell\" type=\"push\" title=\"Check the GitHub issues\" bezelStyle=\"rounded\" alignment=\"center\" controlSize=\"large\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"SvK-VQ-O9q\">\n                        <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"issuesButton:\" target=\"-2\" id=\"JK2-mR-wtq\"/>\n                    </connections>\n                </button>\n                <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"PHe-ta-hg6\">\n                    <rect key=\"frame\" x=\"194\" y=\"75\" width=\"159\" height=\"40\"/>\n                    <buttonCell key=\"cell\" type=\"push\" title=\"Join Discord Server\" bezelStyle=\"rounded\" alignment=\"center\" controlSize=\"large\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"nVz-89-CnO\">\n                        <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"visitDiscordClick:\" target=\"-2\" id=\"LR9-AA-ISS\"/>\n                    </connections>\n                </button>\n                <textField focusRingType=\"none\" verticalHuggingPriority=\"750\" horizontalCompressionResistancePriority=\"250\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"XIB-RT-Gf7\">\n                    <rect key=\"frame\" x=\"198\" y=\"338\" width=\"504\" height=\"34\"/>\n                    <constraints>\n                        <constraint firstAttribute=\"width\" constant=\"500\" id=\"o5p-sa-qMn\"/>\n                    </constraints>\n                    <textFieldCell key=\"cell\" selectable=\"YES\" title=\"More of a technical issue? We maintain a list of the most common issues with various versions of macOS here. And Little Snitch!\" id=\"dgy-jB-vBw\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <textField focusRingType=\"none\" verticalHuggingPriority=\"750\" horizontalCompressionResistancePriority=\"250\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"GP7-Rh-FNa\">\n                    <rect key=\"frame\" x=\"198\" y=\"223\" width=\"504\" height=\"51\"/>\n                    <constraints>\n                        <constraint firstAttribute=\"width\" constant=\"500\" id=\"5Gh-XF-Wlz\"/>\n                        <constraint firstAttribute=\"width\" relation=\"greaterThanOrEqual\" constant=\"500\" id=\"q9B-PH-fUN\"/>\n                    </constraints>\n                    <textFieldCell key=\"cell\" selectable=\"YES\" id=\"iqc-Ni-hmV\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <string key=\"title\">Can't find what you are looking for? Then please check our issues pages on GitHub, you may find an answer to your question and if you don't, you can ask your question there. </string>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <textField focusRingType=\"none\" verticalHuggingPriority=\"750\" horizontalCompressionResistancePriority=\"250\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"CG1-ie-zJE\">\n                    <rect key=\"frame\" x=\"198\" y=\"125\" width=\"504\" height=\"34\"/>\n                    <constraints>\n                        <constraint firstAttribute=\"width\" constant=\"500\" id=\"qJT-Me-Vmz\"/>\n                        <constraint firstAttribute=\"width\" relation=\"greaterThanOrEqual\" constant=\"500\" id=\"tFJ-aD-Ehb\"/>\n                    </constraints>\n                    <textFieldCell key=\"cell\" selectable=\"YES\" title=\"If you want to follow the development and upcoming versions, we also have a Discord server.\" id=\"55U-cz-G55\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"gLI-ih-SCQ\">\n                    <rect key=\"frame\" x=\"194\" y=\"386\" width=\"129\" height=\"40\"/>\n                    <buttonCell key=\"cell\" type=\"push\" title=\"Check the FAQ\" bezelStyle=\"rounded\" alignment=\"center\" controlSize=\"large\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"AGy-2X-jvi\">\n                        <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"faqButton:\" target=\"-2\" id=\"EtM-Zt-UnJ\"/>\n                    </connections>\n                </button>\n                <textField focusRingType=\"none\" verticalHuggingPriority=\"750\" horizontalCompressionResistancePriority=\"250\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"mu4-R7-C8J\">\n                    <rect key=\"frame\" x=\"198\" y=\"436\" width=\"504\" height=\"17\"/>\n                    <constraints>\n                        <constraint firstAttribute=\"width\" constant=\"500\" id=\"3pd-sp-wiA\"/>\n                    </constraints>\n                    <textFieldCell key=\"cell\" selectable=\"YES\" title=\"Not exactly sure how something works? We got you covered in our new FAQ.\" id=\"cY1-Jx-zNC\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n            </subviews>\n            <constraints>\n                <constraint firstItem=\"CG1-ie-zJE\" firstAttribute=\"top\" secondItem=\"Ccg-Ld-deT\" secondAttribute=\"bottom\" constant=\"20\" id=\"1Qr-yo-Omg\"/>\n                <constraint firstItem=\"gLI-ih-SCQ\" firstAttribute=\"top\" secondItem=\"mu4-R7-C8J\" secondAttribute=\"bottom\" constant=\"16\" id=\"28s-r0-Ykq\"/>\n                <constraint firstItem=\"XIB-RT-Gf7\" firstAttribute=\"top\" secondItem=\"gLI-ih-SCQ\" secondAttribute=\"bottom\" constant=\"20\" id=\"46J-7o-cLa\"/>\n                <constraint firstItem=\"UUX-vU-Iz9\" firstAttribute=\"top\" secondItem=\"XIB-RT-Gf7\" secondAttribute=\"bottom\" constant=\"16\" id=\"6Sz-Lr-dca\"/>\n                <constraint firstItem=\"GP7-Rh-FNa\" firstAttribute=\"leading\" secondItem=\"UUX-vU-Iz9\" secondAttribute=\"leading\" id=\"7MI-sh-iLb\"/>\n                <constraint firstItem=\"GP7-Rh-FNa\" firstAttribute=\"top\" secondItem=\"UUX-vU-Iz9\" secondAttribute=\"bottom\" constant=\"20\" id=\"CUc-SD-fET\"/>\n                <constraint firstItem=\"mu4-R7-C8J\" firstAttribute=\"top\" secondItem=\"fiN-Oe-faj\" secondAttribute=\"bottom\" constant=\"20\" id=\"D22-Uw-hna\"/>\n                <constraint firstItem=\"fiN-Oe-faj\" firstAttribute=\"leading\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"leading\" constant=\"200\" id=\"FAF-fp-GRn\"/>\n                <constraint firstItem=\"Ccg-Ld-deT\" firstAttribute=\"top\" secondItem=\"GP7-Rh-FNa\" secondAttribute=\"bottom\" constant=\"16\" id=\"Lyo-pv-39x\"/>\n                <constraint firstItem=\"PHe-ta-hg6\" firstAttribute=\"leading\" secondItem=\"Ccg-Ld-deT\" secondAttribute=\"leading\" id=\"MTA-xM-3TE\"/>\n                <constraint firstItem=\"Ccg-Ld-deT\" firstAttribute=\"leading\" secondItem=\"UUX-vU-Iz9\" secondAttribute=\"leading\" id=\"Oep-xJ-s4B\"/>\n                <constraint firstItem=\"gLI-ih-SCQ\" firstAttribute=\"leading\" secondItem=\"mu4-R7-C8J\" secondAttribute=\"leading\" id=\"Vot-qS-p4W\"/>\n                <constraint firstItem=\"XIB-RT-Gf7\" firstAttribute=\"leading\" secondItem=\"mu4-R7-C8J\" secondAttribute=\"leading\" id=\"g0q-eb-iaJ\"/>\n                <constraint firstItem=\"XIB-RT-Gf7\" firstAttribute=\"leading\" secondItem=\"fiN-Oe-faj\" secondAttribute=\"leading\" id=\"hjf-tl-Za5\"/>\n                <constraint firstAttribute=\"width\" relation=\"greaterThanOrEqual\" constant=\"811\" id=\"iH6-Nd-T12\"/>\n                <constraint firstItem=\"PHe-ta-hg6\" firstAttribute=\"top\" secondItem=\"CG1-ie-zJE\" secondAttribute=\"bottom\" constant=\"16\" id=\"qIx-97-UKf\"/>\n                <constraint firstItem=\"CG1-ie-zJE\" firstAttribute=\"leading\" secondItem=\"Ccg-Ld-deT\" secondAttribute=\"leading\" id=\"tdH-Pa-Rap\"/>\n                <constraint firstItem=\"UUX-vU-Iz9\" firstAttribute=\"leading\" secondItem=\"XIB-RT-Gf7\" secondAttribute=\"leading\" id=\"tmA-eS-hqD\"/>\n                <constraint firstAttribute=\"height\" relation=\"greaterThanOrEqual\" constant=\"530\" id=\"vdg-3G-mNt\"/>\n                <constraint firstItem=\"fiN-Oe-faj\" firstAttribute=\"top\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"top\" constant=\"40\" id=\"woO-AF-o4Y\"/>\n            </constraints>\n            <point key=\"canvasLocation\" x=\"-168\" y=\"135\"/>\n        </customView>\n    </objects>\n</document>\n"
  },
  {
    "path": "Resources/MainUI/Infos panels/InfoViewController.swift",
    "content": "//\n//  InfoViewController.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 17/07/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Cocoa\n\nclass InfoViewController: NSViewController {\n\n    @IBOutlet var versionLabel: NSTextField!\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n\n        versionLabel.stringValue = Aerial.helper.version\n    }\n\n    @IBAction func donateButton(_ sender: Any) {\n        let workspace = NSWorkspace.shared\n        let url = URL(string: \"https://ko-fi.com/A0A32385Y\")!\n        workspace.open(url)\n    }\n\n    @IBAction func iconWebsiteButton(_ sender: Any) {\n        let workspace = NSWorkspace.shared\n        let url = URL(string: \"https://infernodesign.com\")!\n        workspace.open(url)\n    }\n}\n"
  },
  {
    "path": "Resources/MainUI/Infos panels/InfoViewController.xib",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.Cocoa.XIB\" version=\"3.0\" toolsVersion=\"22113.1\" targetRuntime=\"MacOSX.Cocoa\" propertyAccessControl=\"none\" useAutolayout=\"YES\" customObjectInstantitationMethod=\"direct\">\n    <dependencies>\n        <deployment identifier=\"macosx\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.CocoaPlugin\" version=\"22113.1\"/>\n        <capability name=\"documents saved in the Xcode 8 format\" minToolsVersion=\"8.0\"/>\n    </dependencies>\n    <objects>\n        <customObject id=\"-2\" userLabel=\"File's Owner\" customClass=\"InfoViewController\" customModule=\"Aerial\" customModuleProvider=\"target\">\n            <connections>\n                <outlet property=\"versionLabel\" destination=\"ceu-gu-KNt\" id=\"W5n-Yd-PJM\"/>\n                <outlet property=\"view\" destination=\"Hz6-mo-xeY\" id=\"0bl-1N-x8E\"/>\n            </connections>\n        </customObject>\n        <customObject id=\"-1\" userLabel=\"First Responder\" customClass=\"FirstResponder\"/>\n        <customObject id=\"-3\" userLabel=\"Application\" customClass=\"NSObject\"/>\n        <customView translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Hz6-mo-xeY\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"811\" height=\"530\"/>\n            <subviews>\n                <customView translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"wIm-3a-mSi\">\n                    <rect key=\"frame\" x=\"36\" y=\"96\" width=\"740\" height=\"394\"/>\n                    <subviews>\n                        <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"mef-02-T9r\">\n                            <rect key=\"frame\" x=\"358\" y=\"187\" width=\"304\" height=\"68\"/>\n                            <constraints>\n                                <constraint firstAttribute=\"width\" constant=\"300\" id=\"Hw7-YP-zzd\"/>\n                            </constraints>\n                            <textFieldCell key=\"cell\" id=\"GBy-sg-YND\">\n                                <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                <string key=\"title\">A free, open source, macOS Screen Saver developed and maintained by Guillaume Louel. \n\nEnjoying Aerial? </string>\n                                <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                            </textFieldCell>\n                        </textField>\n                        <imageView horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"T8n-jN-Ee4\">\n                            <rect key=\"frame\" x=\"20\" y=\"54\" width=\"320\" height=\"320\"/>\n                            <constraints>\n                                <constraint firstAttribute=\"width\" constant=\"320\" id=\"hRR-xq-21J\"/>\n                                <constraint firstAttribute=\"height\" constant=\"320\" id=\"ulF-hQ-vYE\"/>\n                            </constraints>\n                            <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" image=\"icon-512\" id=\"2e6-aG-RVX\"/>\n                        </imageView>\n                        <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"ceu-gu-KNt\">\n                            <rect key=\"frame\" x=\"358\" y=\"271\" width=\"134\" height=\"17\"/>\n                            <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"Version 123456789\" id=\"3BT-Co-yYW\">\n                                <font key=\"font\" metaFont=\"systemMedium\" size=\"14\"/>\n                                <color key=\"textColor\" name=\"secondaryLabelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                            </textFieldCell>\n                        </textField>\n                        <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"42t-wb-whP\">\n                            <rect key=\"frame\" x=\"358\" y=\"296\" width=\"98\" height=\"43\"/>\n                            <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"Aerial\" id=\"yQI-eW-wVq\">\n                                <font key=\"font\" metaFont=\"systemSemibold\" size=\"36\"/>\n                                <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                            </textFieldCell>\n                        </textField>\n                        <button translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Se0-cG-8jI\">\n                            <rect key=\"frame\" x=\"360\" y=\"135\" width=\"143\" height=\"36\"/>\n                            <buttonCell key=\"cell\" type=\"square\" bezelStyle=\"shadowlessSquare\" image=\"kofi1\" imagePosition=\"only\" alignment=\"center\" imageScaling=\"proportionallyUpOrDown\" inset=\"2\" id=\"xyx-wf-mwp\">\n                                <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                                <font key=\"font\" metaFont=\"system\"/>\n                            </buttonCell>\n                            <connections>\n                                <action selector=\"donateButton:\" target=\"-2\" id=\"Qdf-Yf-w2H\"/>\n                            </connections>\n                        </button>\n                    </subviews>\n                    <constraints>\n                        <constraint firstAttribute=\"width\" constant=\"740\" id=\"2zV-E4-Wa6\"/>\n                        <constraint firstAttribute=\"height\" constant=\"394\" id=\"45p-zl-xFg\"/>\n                        <constraint firstItem=\"Se0-cG-8jI\" firstAttribute=\"leading\" secondItem=\"mef-02-T9r\" secondAttribute=\"leading\" id=\"RNF-l1-dLv\"/>\n                        <constraint firstItem=\"T8n-jN-Ee4\" firstAttribute=\"leading\" secondItem=\"wIm-3a-mSi\" secondAttribute=\"leading\" constant=\"20\" id=\"SFW-Dl-MLg\"/>\n                        <constraint firstItem=\"T8n-jN-Ee4\" firstAttribute=\"top\" secondItem=\"wIm-3a-mSi\" secondAttribute=\"top\" constant=\"20\" id=\"bLk-yy-evl\"/>\n                        <constraint firstItem=\"mef-02-T9r\" firstAttribute=\"leading\" secondItem=\"42t-wb-whP\" secondAttribute=\"leading\" id=\"c7e-Ls-aKb\"/>\n                        <constraint firstItem=\"ceu-gu-KNt\" firstAttribute=\"leading\" secondItem=\"42t-wb-whP\" secondAttribute=\"leading\" id=\"eGo-aw-Dvi\"/>\n                        <constraint firstItem=\"mef-02-T9r\" firstAttribute=\"top\" secondItem=\"ceu-gu-KNt\" secondAttribute=\"bottom\" constant=\"16\" id=\"ege-Tu-444\"/>\n                        <constraint firstItem=\"Se0-cG-8jI\" firstAttribute=\"top\" secondItem=\"mef-02-T9r\" secondAttribute=\"bottom\" constant=\"16\" id=\"iFh-2s-NRY\"/>\n                        <constraint firstItem=\"ceu-gu-KNt\" firstAttribute=\"top\" secondItem=\"42t-wb-whP\" secondAttribute=\"bottom\" constant=\"8\" id=\"lNf-ed-2ne\"/>\n                        <constraint firstItem=\"42t-wb-whP\" firstAttribute=\"top\" secondItem=\"wIm-3a-mSi\" secondAttribute=\"top\" constant=\"55\" id=\"wPb-Uz-1zt\"/>\n                        <constraint firstItem=\"42t-wb-whP\" firstAttribute=\"leading\" secondItem=\"T8n-jN-Ee4\" secondAttribute=\"trailing\" constant=\"20\" id=\"xWn-Yo-X0G\"/>\n                    </constraints>\n                </customView>\n                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"1H8-uB-MG3\">\n                    <rect key=\"frame\" x=\"245\" y=\"17\" width=\"321\" height=\"17\"/>\n                    <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" alignment=\"center\" title=\"Apple TV and tvOS are trademarks of Apple Inc. \" id=\"J9M-tH-MlW\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"secondaryLabelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Kfe-gm-Zg6\">\n                    <rect key=\"frame\" x=\"4\" y=\"4\" width=\"205\" height=\"40\"/>\n                    <buttonCell key=\"cell\" type=\"push\" title=\" Icon by Inferno Design\" bezelStyle=\"rounded\" image=\"LogoIcon-128px\" imagePosition=\"leading\" alignment=\"center\" controlSize=\"large\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"NHO-vH-0M9\">\n                        <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"iconWebsiteButton:\" target=\"-2\" id=\"c3F-VO-QHa\"/>\n                    </connections>\n                </button>\n            </subviews>\n            <constraints>\n                <constraint firstAttribute=\"bottom\" secondItem=\"1H8-uB-MG3\" secondAttribute=\"bottom\" constant=\"17\" id=\"KTe-3H-4DL\"/>\n                <constraint firstItem=\"wIm-3a-mSi\" firstAttribute=\"centerX\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"centerX\" id=\"Q9B-84-Whr\"/>\n                <constraint firstItem=\"1H8-uB-MG3\" firstAttribute=\"leading\" relation=\"greaterThanOrEqual\" secondItem=\"Kfe-gm-Zg6\" secondAttribute=\"trailing\" constant=\"20\" id=\"RIb-nL-c1c\"/>\n                <constraint firstItem=\"Kfe-gm-Zg6\" firstAttribute=\"leading\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"leading\" constant=\"10\" id=\"VLz-Ln-AdL\"/>\n                <constraint firstAttribute=\"height\" relation=\"greaterThanOrEqual\" constant=\"530\" id=\"hSp-LP-MwV\"/>\n                <constraint firstItem=\"1H8-uB-MG3\" firstAttribute=\"centerX\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"centerX\" id=\"jQ5-G3-md3\"/>\n                <constraint firstAttribute=\"bottom\" secondItem=\"Kfe-gm-Zg6\" secondAttribute=\"bottom\" constant=\"10\" id=\"soO-ar-asL\"/>\n                <constraint firstAttribute=\"width\" relation=\"greaterThanOrEqual\" constant=\"811\" id=\"tb7-rB-jCx\"/>\n                <constraint firstItem=\"wIm-3a-mSi\" firstAttribute=\"top\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"top\" constant=\"40\" id=\"wc8-8H-2BZ\"/>\n            </constraints>\n            <point key=\"canvasLocation\" x=\"-58.5\" y=\"48\"/>\n        </customView>\n        <imageView horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" id=\"bHt-IO-dEN\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"48\" height=\"48\"/>\n            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n            <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" id=\"LDu-29-p5l\"/>\n            <point key=\"canvasLocation\" x=\"-163\" y=\"-288\"/>\n        </imageView>\n    </objects>\n    <resources>\n        <image name=\"LogoIcon-128px\" width=\"128\" height=\"143\"/>\n        <image name=\"icon-512\" width=\"512\" height=\"512\"/>\n        <image name=\"kofi1\" width=\"142.5\" height=\"36\"/>\n    </resources>\n</document>\n"
  },
  {
    "path": "Resources/MainUI/PanelWindowController.swift",
    "content": "//\n//  PanelWindowController.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 15/07/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Cocoa\n\n@objc class PanelWindowController: NSWindowController {\n    var firstSetupWindowController: FirstSetupWindowController?\n\n    var splitVC: NSSplitViewController?\n    var videosVC: VideosViewController?\n    var sidebarVC: SidebarViewController?\n\n    var nowPlayingItem: NSSplitViewItem?             // New main view\n\n    var videoViewItem: NSSplitViewItem?             // Main video view\n    // Infos\n    var infoViewItem: NSSplitViewItem?\n    var creditsViewItem: NSSplitViewItem?\n    var helpViewItem: NSSplitViewItem?\n\n    // Settings\n    var sourcesViewItem: NSSplitViewItem?\n    var timeViewItem: NSSplitViewItem?\n    var displaysViewItem: NSSplitViewItem?\n    var brightnessViewItem: NSSplitViewItem?\n    var cacheViewItem: NSSplitViewItem?\n    var overlaysViewItem: NSSplitViewItem?\n    var filtersViewItem: NSSplitViewItem?\n    var advancedViewItem: NSSplitViewItem?\n    \n    var currentPath: String?\n\n    convenience init() {\n        self.init(windowNibName: \"PanelWindowController\")\n    }\n\n    override func windowDidLoad() {\n        // debugLog(\"PWC2 wdl: Aerial version \\(Aerial.version)\")\n        super.windowDidLoad()\n        currentPath = \"location:all\"\n\n        splitVC = NSSplitViewController()   // This is the core of ui V2, we dynamically change the right view controller based on what's on the left\n        \n        \n        // We always need to specify a bundle manually, auto loading from bundle\n        // does not work for screen savers when compiled as plugins\n        let bundle = Bundle(for: PanelWindowController.self)\n\n        videosVC = VideosViewController(nibName: .init(\"VideosViewController\"), bundle: bundle)\n\n        let nowPlayingVC = NowPlayingViewController(nibName: .init(\"NowPlayingViewController\"), bundle: bundle)\n\n        // Infos\n        let infoVC = InfoViewController(nibName: .init(\"InfoViewController\"), bundle: bundle)\n        let creditsVC = CreditsViewController(nibName: .init(\"CreditsViewController\"), bundle: bundle)\n        let helpVC = HelpViewController(nibName: .init(\"HelpViewController\"), bundle: bundle)\n\n        // Various settings\n        let sourcesVC = SourcesViewController(nibName: .init(\"SourcesViewController\"), bundle: bundle)\n        let timeVC = TimeViewController(nibName: .init(\"TimeViewController\"), bundle: bundle)\n        let displaysVC = DisplaysViewController(nibName: .init(\"DisplaysViewController\"), bundle: bundle)\n        let brightnessVC = BrightnessViewController(nibName: .init(\"BrightnessViewController\"), bundle: bundle)\n        let cacheVC = CacheViewController(nibName: .init(\"CacheViewController\"), bundle: bundle)\n        let companionCacheVC = CompanionCacheViewController(nibName: .init(\"CompanionCacheViewController\"), bundle: bundle)\n        let overlaysVC = OverlaysViewController(nibName: .init(\"OverlaysViewController\"), bundle: bundle)\n        let filtersVC = FiltersViewController(nibName: .init(\"FiltersViewController\"), bundle: bundle)\n        let advancedVC = AdvancedViewController(nibName: .init(\"AdvancedViewController\"), bundle: bundle)\n        advancedVC.windowController = self\n\n        // We do the sidebar last, as it bubble up events to the other ones\n        sidebarVC = SidebarViewController(nibName: .init(\"SidebarViewController\"), bundle: bundle)\n        sidebarVC!.windowController = self\n\n        // Also set the Aerial helper\n        Aerial.helper.windowController = self\n\n        // Create all the view items for the right panel\n        nowPlayingItem = NSSplitViewItem(viewController: nowPlayingVC)\n        videoViewItem = NSSplitViewItem(viewController: videosVC!)\n\n        // Infos\n        infoViewItem = NSSplitViewItem(viewController: infoVC)\n        creditsViewItem = NSSplitViewItem(viewController: creditsVC)\n        helpViewItem = NSSplitViewItem(viewController: helpVC)\n        // All the settings have individual controllers\n        sourcesViewItem = NSSplitViewItem(viewController: sourcesVC)\n        timeViewItem = NSSplitViewItem(viewController: timeVC)\n        displaysViewItem = NSSplitViewItem(viewController: displaysVC)\n        brightnessViewItem = NSSplitViewItem(viewController: brightnessVC)\n        if Aerial.helper.underCompanion {\n            cacheViewItem = NSSplitViewItem(viewController: companionCacheVC)\n        } else {\n            cacheViewItem = NSSplitViewItem(viewController: cacheVC)\n        }\n        overlaysViewItem = NSSplitViewItem(viewController: overlaysVC)\n        filtersViewItem = NSSplitViewItem(viewController: filtersVC)\n        advancedViewItem = NSSplitViewItem(viewController: advancedVC)\n\n        splitVC!.addSplitViewItem(NSSplitViewItem(sidebarWithViewController: sidebarVC!))\n        splitVC!.addSplitViewItem(videoViewItem!)\n\n        splitVC!.splitViewItems[0].canCollapse = false\n        splitVC!.splitViewItems[1].canCollapse = false\n        window?.contentViewController = splitVC\n        // PrefsAdvanced.firstTimeSetup = false\n        doFirstTimeSetup()\n\n        debugLog(\"/PWC2 wdl\")\n    }\n\n    func stopVideo() {\n        videosVC?.stopVideo()\n    }\n\n    func doFirstTimeSetup() {\n        if PrefsAdvanced.firstTimeSetup == false && firstSetupWindowController == nil {\n            let bundle = Bundle(for: PanelWindowController.self)\n            // We also load our CustomVideos nib here\n\n            firstSetupWindowController = FirstSetupWindowController()\n            var topLevelObjects: NSArray? = NSArray()\n            if !bundle.loadNibNamed(NSNib.Name(\"FirstSetupWindowController\"),\n                                owner: firstSetupWindowController,\n                                topLevelObjects: &topLevelObjects) {\n                errorLog(\"Could not load nib for CustomVideos, please report\")\n            }\n            DispatchQueue.main.async {\n                self.firstSetupWindowController!.windowDidLoad()\n                self.firstSetupWindowController!.showWindow(self)\n                self.firstSetupWindowController!.window!.makeKeyAndOrderFront(self)\n            }\n        }\n    }\n\n    // Switch from one menu list to another\n    func switchFrom(_ from: SidebarMenus, to: SidebarMenus) {\n        // Ugh...\n        guard let splitVC = splitVC,\n              let nowPlayingItem = nowPlayingItem,\n              let videoViewItem = videoViewItem,\n              let sourcesViewItem = sourcesViewItem,\n              let infoViewItem = infoViewItem,\n              from != to\n              else {\n            return\n        }\n\n        splitVC.removeChild(at: 1)\n\n        // Put new\n        switch to {\n        case .modern:\n            splitVC.addSplitViewItem(nowPlayingItem)\n        case .videos:\n            splitVC.addSplitViewItem(videoViewItem)\n        case.settings:\n            splitVC.addSplitViewItem(sourcesViewItem)\n        case.infos:\n            splitVC.addSplitViewItem(infoViewItem)\n        }\n    }\n\n    //\n    func browseTo(_ path: String) {\n        guard let splitVC = splitVC,\n              let sidebarVC = sidebarVC,\n              let videosVC = videosVC else {\n                  return\n              }\n\n        // Remove the old one\n        splitVC.removeChild(at: 1)\n        // put up the video view\n        splitVC.addSplitViewItem(videoViewItem!)\n        sidebarVC.sidebarOutlineView.selectRowIndexes([2], byExtendingSelection: false)\n        videosVC.reloadPath(path: path)\n    }\n\n    // Switch from one source to another\n    func switchTo(_ path: String) {\n        //print(\"switch to :\" + path)\n\n        guard let currentPath = currentPath,\n              let videosVC = videosVC,\n              path != currentPath else {\n            //print(\"switch init issue\")\n            return\n        }\n\n        if path.starts(with: \"modern:\") {\n            let idx = path.firstIndex(of: \":\")\n            switchToModern(String(path[idx!...].dropFirst())) // Oh Swift...\n        }\n\n        if path.starts(with: \"videos:\") {\n            let idx = path.firstIndex(of: \":\")\n            videosVC.reloadFor(path: String(path[idx!...].dropFirst())) // Oh Swift...\n            switchToModern(String(path[idx!...].dropFirst())) // Oh Swift...\n        }\n\n        if path.starts(with: \"settings:\") {\n            let idx = path.firstIndex(of: \":\")\n            switchToSettings(String(path[idx!...].dropFirst())) // Oh Swift...\n        }\n\n        if path.starts(with: \"infos:\") {\n            let idx = path.firstIndex(of: \":\")\n            switchToInfos(String(path[idx!...].dropFirst())) // Oh Swift...\n        }\n\n        // Save the new path\n        self.currentPath = path\n    }\n\n    func switchToModern(_ path: String) {\n        guard let splitVC = splitVC else {\n            return\n        }\n\n        // Remove the old one\n        splitVC.removeChild(at: 1)\n        switch path {\n        case \"nowplaying\":\n            splitVC.addSplitViewItem(nowPlayingItem!)\n        default:\n            splitVC.addSplitViewItem(videoViewItem!)\n        }\n    }\n\n    func switchToSettings(_ path: String) {\n        guard let splitVC = splitVC else {\n            return\n        }\n\n        // Remove the old one\n        splitVC.removeChild(at: 1)\n        switch path {\n        case \"sources\":\n            splitVC.addSplitViewItem(sourcesViewItem!)\n        case \"time\":\n            splitVC.addSplitViewItem(timeViewItem!)\n        case \"displays\":\n            splitVC.addSplitViewItem(displaysViewItem!)\n        case \"brightness\":\n            splitVC.addSplitViewItem(brightnessViewItem!)\n        case \"cache\":\n            splitVC.addSplitViewItem(cacheViewItem!)\n        case \"overlays\":\n            splitVC.addSplitViewItem(overlaysViewItem!)\n        case \"filters\":\n            splitVC.addSplitViewItem(filtersViewItem!)\n        default: // case \"advanced\":\n            splitVC.addSplitViewItem(advancedViewItem!)\n        }\n    }\n\n    func switchToInfos(_ path: String) {\n        guard let splitVC = splitVC else {\n            return\n        }\n        // Remove the old one\n        splitVC.removeChild(at: 1)\n\n        switch path {\n        // Infos\n        case \"about\":\n            splitVC.addSplitViewItem(infoViewItem!)\n        case \"credits\":\n            splitVC.addSplitViewItem(creditsViewItem!)\n        default: // case \"help\":\n            splitVC.addSplitViewItem(helpViewItem!)\n        }\n    }\n\n    func updateViewInPlace() {\n        if currentPath!.starts(with: \"videos:\") {\n            videosVC!.updateInPlace()\n        } else {\n            debugLog(\"download callback happenning but we moved away\")\n        }\n    }\n\n}\n\nextension PanelWindowController: NSWindowDelegate {\n    func windowDidBecomeKey(_ notification: Notification) {\n        if (notification.object as? NSWindow) == self.window {\n            // doFirstTimeSetup()\n        }\n    }\n}\n"
  },
  {
    "path": "Resources/MainUI/PanelWindowController.xib",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.Cocoa.XIB\" version=\"3.0\" toolsVersion=\"23094\" targetRuntime=\"MacOSX.Cocoa\" propertyAccessControl=\"none\" useAutolayout=\"YES\" customObjectInstantitationMethod=\"direct\">\n    <dependencies>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.CocoaPlugin\" version=\"23094\"/>\n        <capability name=\"documents saved in the Xcode 8 format\" minToolsVersion=\"8.0\"/>\n    </dependencies>\n    <objects>\n        <customObject id=\"-2\" userLabel=\"File's Owner\" customClass=\"PanelWindowController\" customModule=\"Aerial\" customModuleProvider=\"target\">\n            <connections>\n                <outlet property=\"window\" destination=\"F0z-JX-Cv5\" id=\"gIp-Ho-8D9\"/>\n            </connections>\n        </customObject>\n        <customObject id=\"-1\" userLabel=\"First Responder\" customClass=\"FirstResponder\"/>\n        <customObject id=\"-3\" userLabel=\"Application\" customClass=\"NSObject\"/>\n        <window identifier=\"preferencesWindow\" title=\"Window\" allowsToolTipsWhenApplicationIsInactive=\"NO\" autorecalculatesKeyViewLoop=\"NO\" restorable=\"NO\" releasedWhenClosed=\"NO\" visibleAtLaunch=\"NO\" animationBehavior=\"default\" titleVisibility=\"hidden\" id=\"F0z-JX-Cv5\">\n            <windowStyleMask key=\"styleMask\" titled=\"YES\" closable=\"YES\" resizable=\"YES\"/>\n            <windowPositionMask key=\"initialPositionMask\" leftStrut=\"YES\" rightStrut=\"YES\" topStrut=\"YES\" bottomStrut=\"YES\"/>\n            <rect key=\"contentRect\" x=\"196\" y=\"240\" width=\"830\" height=\"542\"/>\n            <rect key=\"screenRect\" x=\"0.0\" y=\"0.0\" width=\"2560\" height=\"1415\"/>\n            <view key=\"contentView\" wantsLayer=\"YES\" id=\"se5-gp-TjO\">\n                <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"830\" height=\"542\"/>\n                <autoresizingMask key=\"autoresizingMask\"/>\n            </view>\n            <connections>\n                <outlet property=\"delegate\" destination=\"-2\" id=\"0bl-1N-AYu\"/>\n            </connections>\n            <point key=\"canvasLocation\" x=\"314\" y=\"280\"/>\n        </window>\n    </objects>\n</document>\n"
  },
  {
    "path": "Resources/MainUI/Settings panels/AdvancedViewController.swift",
    "content": "//\n//  AdvancedViewController.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 18/07/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Cocoa\nimport AVFoundation\nimport VideoToolbox\n\nclass AdvancedViewController: NSViewController {\n    var windowController: PanelWindowController?\n    var firstSetupWindowController: FirstSetupWindowController?\n\n    @IBOutlet var scrollView: NSScrollView!\n    \n    @IBOutlet var popoverVideoFormat: NSPopover!\n\n    @IBOutlet var popoverH264Indicator: NSButton!\n    @IBOutlet var popoverHEVCIndicator: NSButton!\n    @IBOutlet var popoverH264Label: NSTextField!\n    @IBOutlet var popoverHEVCLabel: NSTextField!\n\n    @IBOutlet var popoverOnBattery: NSPopover!\n\n    @IBOutlet var videoFormatPopup: NSPopUpButton!\n    // We need to hide HDR pre-Catalina\n    @IBOutlet var menu1080pHDR: NSMenuItem!\n    @IBOutlet var menu4KHDR: NSMenuItem!\n\n    @IBOutlet var videoFadesPopup: NSPopUpButton!\n\n    @IBOutlet weak var invertColorsCheckbox: NSButton!\n\n    @IBOutlet var rightArrowSkipCheckbox: NSButton!\n    @IBOutlet var muteSoundCheckbox: NSButton!\n\n    @IBOutlet weak var muteAllMacOSSoundsCheckbox: NSButton!\n    @IBOutlet var highQualityTextCheckbox: NSButton!\n\n    @IBOutlet var favorOrientationCheckbox: NSButton!\n    @IBOutlet var autoplayPreviews: NSButton!\n\n    @IBOutlet var onBatteryPopup: NSPopUpButton!\n\n    @IBOutlet var languagePopup: NSPopUpButton!\n    @IBOutlet var languageLabel: NSTextField!\n\n    @IBOutlet var debugCheckbox: NSButton!\n\n    @IBOutlet var showLogButton: NSButton!\n\n    @IBOutlet var launchSetupAgain: NSButton!\n    var originalFormat: VideoFormat?\n    override func viewDidLoad() {\n        super.viewDidLoad()\n\n        DispatchQueue.main.async {\n            self.scrollView.contentView.scroll(NSMakePoint(0,0))\n        }\n        \n        // HEVC is available only in macOS 10.13+\n        if #available(OSX 10.13, *) {\n            videoFormatPopup.selectItem(at: PrefsVideos.videoFormat.rawValue)\n        } else {\n            // We reset to 1080p below 10.13\n            PrefsVideos.videoFormat = VideoFormat.v1080pH264\n            videoFormatPopup.selectItem(at: PrefsVideos.videoFormat.rawValue)\n            videoFormatPopup.isEnabled = false\n        }\n\n        // Save this for future use\n        originalFormat = PrefsVideos.videoFormat\n\n        videoFadesPopup.selectItem(at: PrefsVideos.fadeMode.rawValue)\n\n        // We need catalina for HDR ! And we can't use right arrow to skip in Catalina\n        if #available(OSX 10.15, *) {\n            rightArrowSkipCheckbox.isEnabled = false\n        } else {\n            menu1080pHDR.isHidden = true\n            menu4KHDR.isHidden = true\n        }\n\n        if !PrefsVideos.allowSkips {\n            rightArrowSkipCheckbox.state = .off\n        }\n\n        invertColorsCheckbox.state = PrefsAdvanced.invertColors ? .on : .off\n        highQualityTextCheckbox.state = PrefsInfo.highQualityTextRendering ? .on : .off\n\n        muteSoundCheckbox.state = PrefsAdvanced.muteSound ? .on : .off\n        muteAllMacOSSoundsCheckbox.state = PrefsAdvanced.muteGlobalSound ? .on : .off\n        autoplayPreviews.state = PrefsAdvanced.autoPlayPreviews ? .on : .off\n        favorOrientationCheckbox.state = PrefsAdvanced.favorOrientation ? .on : .off\n\n        onBatteryPopup.selectItem(at: PrefsVideos.onBatteryMode.rawValue)\n\n        if PrefsAdvanced.debugMode {\n            debugCheckbox.state = .on\n        }\n\n        let poisp = PoiStringProvider.sharedInstance\n        languagePopup.selectItem(at: poisp.getLanguagePosition())\n\n        // Grab preferred language as proper string\n        languageLabel.stringValue = Aerial.helper.getPreferredLanguage()\n\n        showLogButton.setIcons(\"folder\")\n        launchSetupAgain.setIcons(\"aspectratio\")\n        setupPopover()\n    }\n\n    func setupPopover() {\n        // Help popover, GVA detection requires 10.13\n        if #available(OSX 10.13, *) {\n            if !VTIsHardwareDecodeSupported(kCMVideoCodecType_H264) {\n                popoverH264Label.stringValue = \"H264 acceleration not supported\"\n                popoverH264Indicator.image = NSImage(named: NSImage.statusUnavailableName)\n            }\n            if !VTIsHardwareDecodeSupported(kCMVideoCodecType_HEVC) {\n                popoverHEVCLabel.stringValue = \"HEVC Main10 acceleration not supported\"\n                popoverHEVCIndicator.image = NSImage(named: NSImage.statusUnavailableName)\n            } else {\n                let hardwareDetection = HardwareDetection.sharedInstance\n                switch hardwareDetection.isHEVCMain10HWDecodingAvailable() {\n                case .supported:\n                    popoverHEVCLabel.stringValue = \"HEVC Main10 acceleration is supported\"\n                    popoverHEVCIndicator.image = NSImage(named: NSImage.statusAvailableName)\n                case .notsupported:\n                    popoverHEVCLabel.stringValue = \"HEVC Main10 acceleration is not supported\"\n                    popoverHEVCIndicator.image = NSImage(named: NSImage.statusUnavailableName)\n                case .partial:\n                    popoverHEVCLabel.stringValue = \"HEVC Main10 acceleration is partially supported\"\n                    popoverHEVCIndicator.image = NSImage(named: NSImage.statusPartiallyAvailableName)\n                default:\n                    popoverHEVCLabel.stringValue = \"HEVC Main10 acceleration status unknown\"\n                    popoverHEVCIndicator.image = NSImage(named: NSImage.cautionName)\n                }\n            }\n        } else {\n            // Fallback on earlier versions\n            popoverHEVCIndicator.isHidden = true\n            popoverH264Indicator.image = NSImage(named: NSImage.cautionName)\n            popoverH264Label.stringValue = \"macOS 10.13 or above required\"\n            popoverHEVCLabel.stringValue = \"Hardware acceleration status unknown\"\n        }\n    }\n\n    @IBAction func launchSetupAgainClick(_ sender: NSButton) {\n        if firstSetupWindowController == nil {\n            let bundle = Bundle(for: PanelWindowController.self)\n            // We also load our CustomVideos nib here\n\n            firstSetupWindowController = FirstSetupWindowController()\n            var topLevelObjects: NSArray? = NSArray()\n            if !bundle.loadNibNamed(NSNib.Name(\"FirstSetupWindowController\"),\n                                owner: firstSetupWindowController,\n                                topLevelObjects: &topLevelObjects) {\n                errorLog(\"Could not load nib for FirstSetupWindowController, please report\")\n            }\n        }\n\n        DispatchQueue.main.async {\n            self.firstSetupWindowController!.windowDidLoad()\n            self.firstSetupWindowController!.showWindow(self)\n            self.firstSetupWindowController!.window!.makeKeyAndOrderFront(self)\n        }\n    }\n\n    @IBAction func videoFormatPopupChange(_ sender: NSPopUpButton) {\n        let candidateFormat = VideoFormat(rawValue: sender.indexOfSelectedItem)!\n\n        if candidateFormat != originalFormat {\n            // swiftlint:disable:next line_length\n            if Aerial.helper.showAlert(question: \"Changing format will delete all videos\", text: \"Changing format will delete your downloaded videos. They will be re-downloaded based on your preferences. \\n\\nYou can also manually redownload videos in Custom Sources.\", button1: \"Change Format and Delete Videos\", button2: \"Cancel\") {\n                PrefsVideos.videoFormat = candidateFormat\n                originalFormat = candidateFormat\n\n                Cache.clearCache()\n                Cache.clearNonCacheableSources()\n                // Sidebar.instance.refreshVideos()\n            } else {\n                videoFormatPopup.selectItem(at: PrefsVideos.videoFormat.rawValue)\n            }\n        } else {\n            PrefsVideos.videoFormat = candidateFormat\n        }\n    }\n\n    @IBAction func invertColorsCheckboxClick(_ sender: NSButton) {\n        PrefsAdvanced.invertColors = sender.state == .on\n    }\n    @IBAction func videoFadesPopupChange(_ sender: NSPopUpButton) {\n        PrefsVideos.fadeMode = FadeMode(rawValue: sender.indexOfSelectedItem)!\n    }\n\n    @IBAction func highQualityTextClick(_ sender: NSButton) {\n        PrefsInfo.highQualityTextRendering = sender.state == .on\n    }\n    @IBAction func rightArrowSkipClick(_ sender: NSButton) {\n        PrefsVideos.allowSkips = sender.state == .on\n    }\n\n    @IBAction func muteSoundClick(_ sender: NSButton) {\n        PrefsAdvanced.muteSound = sender.state == .on\n    }\n\n    @IBAction func muteAllMacOSSoundsClick(_ sender: NSButton) {\n        PrefsAdvanced.muteGlobalSound = sender.state == .on\n    }\n    \n    @IBAction func autoPlaysPreviewsClick(_ sender: NSButton) {\n        PrefsAdvanced.autoPlayPreviews = sender.state == .on\n    }\n\n    @IBAction func favorOrientationClick(_ sender: NSButton) {\n        PrefsAdvanced.favorOrientation = sender.state == .on\n    }\n\n    @IBAction func onBatteryPopupChange(_ sender: NSPopUpButton) {\n        PrefsVideos.onBatteryMode = OnBatteryMode(rawValue: sender.indexOfSelectedItem)!\n    }\n\n    @IBAction func languagePopupChange(_ sender: NSPopUpButton) {\n        let poisp = PoiStringProvider.sharedInstance\n        PrefsAdvanced.ciOverrideLanguage = poisp.getLanguageStringFromPosition(pos: sender.indexOfSelectedItem)\n    }\n\n    @IBAction func debugCheckboxClick(_ sender: NSButton) {\n        PrefsAdvanced.debugMode = sender.state == .on\n    }\n\n    @IBAction func showLogInFinderClick(_ sender: Any) {\n        let logfile = Cache.supportPath.appending(\"/AerialLog.txt\")\n\n        // If we don't have a log, just show the folder\n        if FileManager.default.fileExists(atPath: logfile) == false {\n            NSWorkspace.shared.selectFile(nil, inFileViewerRootedAtPath: Cache.supportPath)\n        } else {\n            NSWorkspace.shared.selectFile(logfile, inFileViewerRootedAtPath: Cache.supportPath)\n        }\n    }\n\n    @IBAction func resetAllSettings(_ sender: NSButton) {\n        if Aerial.helper.showAlert(\n            question: \"Reset all settings?\",\n            text: \"This will reset all your settings. After they are reset, Aerial will close System Preferences, you will have to reload it to access settings again.\\n\\nAre you sure you want to reset your settings?\",\n            button1: \"Reset my settings\",\n            button2: \"Cancel\") {\n\n            let process: Process = Process()\n\n            debugLog(\"clearing old defaults\")\n            process.launchPath = \"/usr/bin/defaults\"\n\n            // First remove old ByHost settings\n            if #available(OSX 10.15, *) {\n                process.arguments = [\"-currentHost\", \"delete\", Aerial.helper.getPreferencesDirectory() + \"ByHost/com.JohnCoates.Aerial\"]\n            } else {\n                process.arguments = [\"-currentHost\", \"delete\", \"com.JohnCoates.Aerial\"]\n            }\n\n            process.launch()\n            process.waitUntilExit()\n\n            let process2: Process = Process()\n\n            debugLog(\"clearing new defaults\")\n            process2.launchPath = \"/usr/bin/defaults\"\n\n            // First remove old ByHost settings\n            if #available(OSX 10.15, *) {\n                process2.arguments = [\"delete\", Aerial.helper.getPreferencesDirectory() + \"com.glouel.Aerial\"]\n            } else {\n                process2.arguments = [\"delete\", \"com.glouel.Aerial\"]\n            }\n\n            process2.launch()\n            process2.waitUntilExit()\n\n            \n            \n            \n\n            Aerial.helper.showInfoAlert(title: \"Settings reset to defaults\", text: \"Your settings were reset to defaults. \\n\\nPlease close Aerial and System Preferences in order to reload them.\")\n        }\n    }\n\n    // Helpers, to move in a model when I have a sec\n\n    @IBAction func helpVideoFormat(_ sender: NSButton) {\n        popoverVideoFormat.show(relativeTo: sender.preparedContentRect, of: sender, preferredEdge: .maxY)\n    }\n\n    @IBAction func helpOnBattery(_ sender: NSButton) {\n        popoverOnBattery.show(relativeTo: sender.preparedContentRect, of: sender, preferredEdge: .maxY)\n    }\n\n    @IBAction func dolbyVisionClick(_ sender: Any) {\n        let workspace = NSWorkspace.shared\n        let url = URL(string: \"https://en.wikipedia.org/wiki/Dolby_Laboratories#Video_processing\")!\n        workspace.open(url)\n    }\n\n    @IBAction func projectPageClick(_ sender: Any) {\n        let workspace = NSWorkspace.shared\n        let url = URL(string: \"https://github.com/JohnCoates/Aerial/blob/master/Documentation/HardwareDecoding.md\")!\n        workspace.open(url)\n    }\n}\n"
  },
  {
    "path": "Resources/MainUI/Settings panels/AdvancedViewController.xib",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.Cocoa.XIB\" version=\"3.0\" toolsVersion=\"23094\" targetRuntime=\"MacOSX.Cocoa\" propertyAccessControl=\"none\" useAutolayout=\"YES\" customObjectInstantitationMethod=\"direct\">\n    <dependencies>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.CocoaPlugin\" version=\"23094\"/>\n        <capability name=\"Image references\" minToolsVersion=\"12.0\"/>\n        <capability name=\"System colors introduced in macOS 10.14\" minToolsVersion=\"10.0\"/>\n        <capability name=\"documents saved in the Xcode 8 format\" minToolsVersion=\"8.0\"/>\n    </dependencies>\n    <objects>\n        <customObject id=\"-2\" userLabel=\"File's Owner\" customClass=\"AdvancedViewController\" customModule=\"Aerial\" customModuleProvider=\"target\">\n            <connections>\n                <outlet property=\"autoplayPreviews\" destination=\"D6x-HI-azM\" id=\"8K9-YC-6pd\"/>\n                <outlet property=\"debugCheckbox\" destination=\"Jfm-Hl-4bN\" id=\"XiF-WF-NLg\"/>\n                <outlet property=\"favorOrientationCheckbox\" destination=\"oe5-rQ-KJu\" id=\"P2e-TZ-j6f\"/>\n                <outlet property=\"highQualityTextCheckbox\" destination=\"aZ7-cT-Z3Y\" id=\"Oz0-Fk-ATM\"/>\n                <outlet property=\"invertColorsCheckbox\" destination=\"NT3-XE-JxM\" id=\"t3F-Ud-BCz\"/>\n                <outlet property=\"languageLabel\" destination=\"xFh-dw-fup\" id=\"ng0-cZ-hbk\"/>\n                <outlet property=\"languagePopup\" destination=\"39U-7I-fEm\" id=\"X38-8k-EEi\"/>\n                <outlet property=\"launchSetupAgain\" destination=\"vYi-Hf-cI5\" id=\"yqJ-SP-aSk\"/>\n                <outlet property=\"menu1080pHDR\" destination=\"rbr-AX-Qap\" id=\"CFs-wI-4me\"/>\n                <outlet property=\"menu4KHDR\" destination=\"D9e-ji-I4Y\" id=\"Pcs-n5-1zI\"/>\n                <outlet property=\"muteAllMacOSSoundsCheckbox\" destination=\"xqc-uN-D8Z\" id=\"pNm-Rz-gM8\"/>\n                <outlet property=\"muteSoundCheckbox\" destination=\"c2Y-BQ-Mg9\" id=\"mFh-GY-ea4\"/>\n                <outlet property=\"onBatteryPopup\" destination=\"ueZ-L1-tKm\" id=\"Uh5-No-e50\"/>\n                <outlet property=\"popoverH264Indicator\" destination=\"a0S-Jv-7q3\" id=\"QNK-Fq-cRs\"/>\n                <outlet property=\"popoverH264Label\" destination=\"Txl-g4-G2k\" id=\"aLG-Wv-vf9\"/>\n                <outlet property=\"popoverHEVCIndicator\" destination=\"Suq-Wx-2D8\" id=\"yLE-1T-EU4\"/>\n                <outlet property=\"popoverHEVCLabel\" destination=\"nz2-xT-PMG\" id=\"G94-a3-cHn\"/>\n                <outlet property=\"popoverOnBattery\" destination=\"r9v-NK-gTh\" id=\"EFa-81-wtw\"/>\n                <outlet property=\"popoverVideoFormat\" destination=\"Tj3-h3-vJZ\" id=\"gyC-Rd-Wyw\"/>\n                <outlet property=\"rightArrowSkipCheckbox\" destination=\"4zW-Lf-b41\" id=\"4zo-2D-C0S\"/>\n                <outlet property=\"scrollView\" destination=\"6Ha-9D-VMf\" id=\"I3d-Mi-ww1\"/>\n                <outlet property=\"showLogButton\" destination=\"Dka-WL-c4U\" id=\"hrx-cM-lP4\"/>\n                <outlet property=\"videoFadesPopup\" destination=\"2PZ-3t-5f8\" id=\"I6x-56-bNY\"/>\n                <outlet property=\"videoFormatPopup\" destination=\"tVO-Se-9Jo\" id=\"SRl-pM-qxB\"/>\n                <outlet property=\"view\" destination=\"Hz6-mo-xeY\" id=\"0bl-1N-x8E\"/>\n            </connections>\n        </customObject>\n        <customObject id=\"-1\" userLabel=\"First Responder\" customClass=\"FirstResponder\"/>\n        <customObject id=\"-3\" userLabel=\"Application\" customClass=\"NSObject\"/>\n        <customView translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Hz6-mo-xeY\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"811\" height=\"715\"/>\n            <subviews>\n                <box boxType=\"custom\" borderType=\"none\" borderWidth=\"0.0\" title=\"Box\" transparent=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"yjL-IP-0lB\">\n                    <rect key=\"frame\" x=\"0.0\" y=\"662\" width=\"811\" height=\"53\"/>\n                    <view key=\"contentView\" id=\"dCt-bT-aI2\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"811\" height=\"53\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <subviews>\n                            <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"nh1-WW-nno\">\n                                <rect key=\"frame\" x=\"52\" y=\"20\" width=\"201\" height=\"17\"/>\n                                <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"Advanced settings and tweaks\" id=\"c2R-sQ-75h\">\n                                    <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                    <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                </textFieldCell>\n                            </textField>\n                            <imageView horizontalHuggingPriority=\"25\" verticalHuggingPriority=\"25\" horizontalCompressionResistancePriority=\"75\" verticalCompressionResistancePriority=\"75\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"DXq-Fc-PfV\">\n                                <rect key=\"frame\" x=\"16\" y=\"3\" width=\"28.5\" height=\"47\"/>\n                                <constraints>\n                                    <constraint firstAttribute=\"height\" constant=\"33\" id=\"ARg-Kb-f9i\"/>\n                                    <constraint firstAttribute=\"width\" constant=\"28\" id=\"oGg-16-n2o\"/>\n                                </constraints>\n                                <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyUpOrDown\" id=\"Sil-Pd-Bb1\">\n                                    <imageReference key=\"image\" image=\"wrench.and.screwdriver\" catalog=\"system\" symbolScale=\"large\"/>\n                                </imageCell>\n                                <color key=\"contentTintColor\" name=\"controlAccentColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                            </imageView>\n                        </subviews>\n                        <constraints>\n                            <constraint firstAttribute=\"bottom\" secondItem=\"DXq-Fc-PfV\" secondAttribute=\"bottom\" constant=\"10\" id=\"9Y8-0O-dXA\"/>\n                            <constraint firstItem=\"nh1-WW-nno\" firstAttribute=\"leading\" secondItem=\"dCt-bT-aI2\" secondAttribute=\"leading\" constant=\"54\" id=\"WoR-F7-YC8\"/>\n                            <constraint firstItem=\"DXq-Fc-PfV\" firstAttribute=\"top\" secondItem=\"dCt-bT-aI2\" secondAttribute=\"top\" constant=\"10\" id=\"XSC-hd-tH1\"/>\n                            <constraint firstItem=\"DXq-Fc-PfV\" firstAttribute=\"leading\" secondItem=\"dCt-bT-aI2\" secondAttribute=\"leading\" constant=\"16\" id=\"XqX-YW-VeF\"/>\n                            <constraint firstItem=\"nh1-WW-nno\" firstAttribute=\"top\" secondItem=\"dCt-bT-aI2\" secondAttribute=\"top\" constant=\"16\" id=\"dV1-br-anP\"/>\n                        </constraints>\n                    </view>\n                    <constraints>\n                        <constraint firstAttribute=\"height\" constant=\"53\" id=\"IkD-6U-Zm8\"/>\n                    </constraints>\n                </box>\n                <scrollView horizontalLineScroll=\"10\" horizontalPageScroll=\"10\" verticalLineScroll=\"10\" verticalPageScroll=\"10\" usesPredominantAxisScrolling=\"NO\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"6Ha-9D-VMf\">\n                    <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"811\" height=\"663\"/>\n                    <clipView key=\"contentView\" id=\"EPP-mS-BQX\">\n                        <rect key=\"frame\" x=\"1\" y=\"1\" width=\"809\" height=\"661\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <subviews>\n                            <customView translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"TLS-nM-OqY\">\n                                <rect key=\"frame\" x=\"0.0\" y=\"51\" width=\"809\" height=\"610\"/>\n                                <subviews>\n                                    <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"XOJ-kW-rZe\">\n                                        <rect key=\"frame\" x=\"227\" y=\"519\" width=\"85\" height=\"17\"/>\n                                        <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" alignment=\"right\" title=\"Video fades:\" id=\"pA2-Es-SqM\">\n                                            <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                            <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                            <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                        </textFieldCell>\n                                    </textField>\n                                    <button toolTip=\"This feature is not available on Catalina and later because of macOS security restrictions\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"4zW-Lf-b41\">\n                                        <rect key=\"frame\" x=\"315\" y=\"433.5\" width=\"215\" height=\"22\"/>\n                                        <buttonCell key=\"cell\" type=\"check\" title=\"Right arrow key to skip video\" bezelStyle=\"regularSquare\" imagePosition=\"left\" controlSize=\"large\" state=\"on\" inset=\"2\" id=\"Rgn-1F-wKS\">\n                                            <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                                            <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                        </buttonCell>\n                                        <connections>\n                                            <action selector=\"rightArrowSkipClick:\" target=\"-2\" id=\"I8E-Rd-dOV\"/>\n                                        </connections>\n                                    </button>\n                                    <popUpButton verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"ueZ-L1-tKm\">\n                                        <rect key=\"frame\" x=\"313\" y=\"234\" width=\"154\" height=\"40\"/>\n                                        <popUpButtonCell key=\"cell\" type=\"push\" title=\"Keep enabled\" bezelStyle=\"rounded\" alignment=\"left\" controlSize=\"large\" lineBreakMode=\"truncatingTail\" state=\"on\" borderStyle=\"borderAndBezel\" imageScaling=\"proportionallyDown\" inset=\"2\" selectedItem=\"IpW-J3-24s\" id=\"iVm-OE-7YZ\">\n                                            <behavior key=\"behavior\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                                            <font key=\"font\" size=\"14\" name=\"HelveticaNeue\"/>\n                                            <menu key=\"menu\" id=\"ju5-fz-KDO\">\n                                                <items>\n                                                    <menuItem title=\"Keep enabled\" state=\"on\" id=\"IpW-J3-24s\"/>\n                                                    <menuItem title=\"Always disable\" id=\"cPU-pi-EsJ\"/>\n                                                    <menuItem title=\"Disable if &lt; 20%\" id=\"w6p-h9-U35\"/>\n                                                </items>\n                                            </menu>\n                                        </popUpButtonCell>\n                                        <connections>\n                                            <action selector=\"onBatteryPopupChange:\" target=\"-2\" id=\"0Yo-oz-dDB\"/>\n                                        </connections>\n                                    </popUpButton>\n                                    <popUpButton toolTip=\"The duration of the fades at the beginning and the end of each video\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"2PZ-3t-5f8\">\n                                        <rect key=\"frame\" x=\"313\" y=\"506\" width=\"120\" height=\"40\"/>\n                                        <popUpButtonCell key=\"cell\" type=\"push\" title=\"1 second\" bezelStyle=\"rounded\" alignment=\"left\" controlSize=\"large\" lineBreakMode=\"truncatingTail\" state=\"on\" borderStyle=\"borderAndBezel\" imageScaling=\"proportionallyDown\" inset=\"2\" selectedItem=\"VtY-HK-i7p\" id=\"2Je-DA-thk\">\n                                            <behavior key=\"behavior\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                                            <font key=\"font\" size=\"14\" name=\"HelveticaNeue\"/>\n                                            <menu key=\"menu\" id=\"5xh-cq-dRg\">\n                                                <items>\n                                                    <menuItem title=\"None\" id=\"ezK-ND-Xmn\"/>\n                                                    <menuItem title=\"0.5 second\" id=\"qLH-T3-AWz\"/>\n                                                    <menuItem title=\"1 second\" state=\"on\" id=\"VtY-HK-i7p\"/>\n                                                    <menuItem title=\"2 seconds\" id=\"xfC-f4-RF9\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                    </menuItem>\n                                                </items>\n                                            </menu>\n                                        </popUpButtonCell>\n                                        <connections>\n                                            <action selector=\"videoFadesPopupChange:\" target=\"-2\" id=\"1eK-tM-QL1\"/>\n                                        </connections>\n                                    </popUpButton>\n                                    <box verticalHuggingPriority=\"750\" boxType=\"separator\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"LK9-Dp-4je\">\n                                        <rect key=\"frame\" x=\"20\" y=\"215\" width=\"769\" height=\"5\"/>\n                                    </box>\n                                    <popUpButton verifyAmbiguity=\"off\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"39U-7I-fEm\">\n                                        <rect key=\"frame\" x=\"313\" y=\"161\" width=\"170\" height=\"40\"/>\n                                        <popUpButtonCell key=\"cell\" type=\"push\" title=\"Preferred\" bezelStyle=\"rounded\" alignment=\"left\" controlSize=\"large\" lineBreakMode=\"truncatingTail\" state=\"on\" borderStyle=\"borderAndBezel\" imageScaling=\"proportionallyDown\" inset=\"2\" selectedItem=\"eac-0Y-vKj\" id=\"TWx-zF-jAK\">\n                                            <behavior key=\"behavior\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                                            <font key=\"font\" size=\"14\" name=\"HelveticaNeue\"/>\n                                            <menu key=\"menu\" id=\"DkR-Wv-ewh\">\n                                                <items>\n                                                    <menuItem title=\"Preferred\" state=\"on\" id=\"eac-0Y-vKj\"/>\n                                                    <menuItem title=\"Arabic\" identifier=\"ar\" id=\"rcZ-AI-naz\"/>\n                                                    <menuItem title=\"Chinese Simplified\" id=\"mYz-1F-BJr\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                    </menuItem>\n                                                    <menuItem title=\"Chinese Traditional\" id=\"GMA-KR-82m\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                    </menuItem>\n                                                    <menuItem title=\"Dutch\" id=\"HV2-Py-inP\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                    </menuItem>\n                                                    <menuItem title=\"English\" id=\"2O1-cb-mbK\"/>\n                                                    <menuItem title=\"French\" id=\"LLT-V7-Qgr\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                    </menuItem>\n                                                    <menuItem title=\"German\" id=\"2aP-1z-Hzo\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                    </menuItem>\n                                                    <menuItem title=\"Hebrew\" id=\"REf-pq-TzN\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                    </menuItem>\n                                                    <menuItem title=\"Hungarian\" id=\"7Gq-94-N1i\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                    </menuItem>\n                                                    <menuItem title=\"Italian\" id=\"DdV-mO-THS\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                    </menuItem>\n                                                    <menuItem title=\"Japanese\" id=\"5kk-ZV-0Ki\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                    </menuItem>\n                                                    <menuItem title=\"Korean\" id=\"0Dm-8H-ah9\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                    </menuItem>\n                                                    <menuItem title=\"Polish\" id=\"ulr-Rn-9L3\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                    </menuItem>\n                                                    <menuItem title=\"Portuguese\" id=\"Gwu-18-6SL\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                    </menuItem>\n                                                    <menuItem title=\"Portuguese (Brazil)\" id=\"JnZ-pc-ZlQ\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                    </menuItem>\n                                                    <menuItem title=\"Russian\" id=\"D53-xA-9jE\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                    </menuItem>\n                                                    <menuItem title=\"Spanish\" id=\"PhL-Od-K1y\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                    </menuItem>\n                                                    <menuItem title=\"Swedish\" id=\"AfW-ma-pQa\" userLabel=\"Swedish\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                    </menuItem>\n                                                    <menuItem title=\"Tagalog\" id=\"ZVx-P2-TGy\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                    </menuItem>\n                                                </items>\n                                            </menu>\n                                        </popUpButtonCell>\n                                        <connections>\n                                            <action selector=\"languagePopupChange:\" target=\"-2\" id=\"Mr7-pn-anj\"/>\n                                        </connections>\n                                    </popUpButton>\n                                    <button toolTip=\"Click for more information on Power Saving\" horizontalHuggingPriority=\"750\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"geu-ZX-2ke\">\n                                        <rect key=\"frame\" x=\"470\" y=\"233\" width=\"35\" height=\"35\"/>\n                                        <buttonCell key=\"cell\" type=\"help\" bezelStyle=\"helpButton\" alignment=\"center\" controlSize=\"large\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"Pe4-WV-Mm2\">\n                                            <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                                            <font key=\"font\" metaFont=\"system\"/>\n                                        </buttonCell>\n                                        <connections>\n                                            <action selector=\"helpOnBattery:\" target=\"-2\" id=\"dX2-Vd-se0\"/>\n                                        </connections>\n                                    </button>\n                                    <button toolTip=\"Debug mode will enable extra debug information messages to be logged. \" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Jfm-Hl-4bN\">\n                                        <rect key=\"frame\" x=\"315\" y=\"70.5\" width=\"112\" height=\"22\"/>\n                                        <buttonCell key=\"cell\" type=\"check\" title=\"Debug mode\" bezelStyle=\"regularSquare\" imagePosition=\"left\" controlSize=\"large\" inset=\"2\" id=\"IpO-lE-bIE\">\n                                            <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                                            <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                        </buttonCell>\n                                        <connections>\n                                            <action selector=\"debugCheckboxClick:\" target=\"-2\" id=\"PSp-I8-bLa\"/>\n                                        </connections>\n                                    </button>\n                                    <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"xFh-dw-fup\">\n                                        <rect key=\"frame\" x=\"316\" y=\"135\" width=\"144\" height=\"17\"/>\n                                        <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" title=\"Your current locale is \" id=\"ZpU-TZ-xXp\">\n                                            <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                            <color key=\"textColor\" name=\"secondaryLabelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                            <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                        </textFieldCell>\n                                    </textField>\n                                    <button toolTip=\"Built in videos don't have sound, but your local videos may have\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"c2Y-BQ-Mg9\">\n                                        <rect key=\"frame\" x=\"315\" y=\"359.5\" width=\"185\" height=\"22\"/>\n                                        <buttonCell key=\"cell\" type=\"check\" title=\"Mute sound from videos\" bezelStyle=\"regularSquare\" imagePosition=\"left\" controlSize=\"large\" state=\"on\" inset=\"2\" id=\"MCe-Ny-bEH\">\n                                            <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                                            <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                        </buttonCell>\n                                        <connections>\n                                            <action selector=\"muteSoundClick:\" target=\"-2\" id=\"jbe-XY-PPY\"/>\n                                        </connections>\n                                    </button>\n                                    <button toolTip=\"Show AerialLog.txt in finder\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Dka-WL-c4U\">\n                                        <rect key=\"frame\" x=\"475\" y=\"60\" width=\"176\" height=\"40\"/>\n                                        <buttonCell key=\"cell\" type=\"push\" title=\"Show Log in Finder\" bezelStyle=\"rounded\" image=\"folder\" catalog=\"system\" imagePosition=\"leading\" alignment=\"center\" alternateImage=\"NSFolder\" controlSize=\"large\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"8fV-Kb-hfT\">\n                                            <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                                            <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                        </buttonCell>\n                                        <connections>\n                                            <action selector=\"showLogInFinderClick:\" target=\"-2\" id=\"AEs-nt-heq\"/>\n                                        </connections>\n                                    </button>\n                                    <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"XVw-x2-MRK\">\n                                        <rect key=\"frame\" x=\"196\" y=\"247\" width=\"116\" height=\"17\"/>\n                                        <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" alignment=\"right\" title=\"When on battery:\" id=\"NuA-Pp-M1N\">\n                                            <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                            <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                            <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                        </textFieldCell>\n                                    </textField>\n                                    <popUpButton toolTip=\"Pick your preferred video format, see help for more information\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"tVO-Se-9Jo\">\n                                        <rect key=\"frame\" x=\"313\" y=\"556\" width=\"131\" height=\"40\"/>\n                                        <popUpButtonCell key=\"cell\" type=\"push\" title=\"1080p H264\" bezelStyle=\"rounded\" alignment=\"left\" controlSize=\"large\" lineBreakMode=\"truncatingTail\" state=\"on\" borderStyle=\"borderAndBezel\" imageScaling=\"proportionallyDown\" inset=\"2\" selectedItem=\"F41-ky-Eg7\" id=\"bjl-nz-Him\">\n                                            <behavior key=\"behavior\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                                            <font key=\"font\" size=\"14\" name=\"HelveticaNeue\"/>\n                                            <menu key=\"menu\" id=\"UvG-P4-sqy\">\n                                                <items>\n                                                    <menuItem title=\"1080p H264\" state=\"on\" id=\"F41-ky-Eg7\"/>\n                                                    <menuItem title=\"1080p HEVC\" id=\"QnL-88-t9e\"/>\n                                                    <menuItem title=\"1080p HDR\" id=\"rbr-AX-Qap\" userLabel=\"1080p HDR\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                    </menuItem>\n                                                    <menuItem title=\"4K HEVC\" id=\"43e-Ow-R4v\"/>\n                                                    <menuItem title=\"4K HDR\" id=\"D9e-ji-I4Y\" userLabel=\"4K HDR\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                    </menuItem>\n                                                    <menuItem title=\"4K 240FPS\" id=\"fEa-Ol-jdD\" userLabel=\"4K HDR\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                    </menuItem>\n                                                </items>\n                                            </menu>\n                                        </popUpButtonCell>\n                                        <connections>\n                                            <action selector=\"videoFormatPopupChange:\" target=\"-2\" id=\"5he-hm-yXX\"/>\n                                        </connections>\n                                    </popUpButton>\n                                    <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" preferredMaxLayoutWidth=\"79\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"iIR-49-5le\">\n                                        <rect key=\"frame\" x=\"229\" y=\"569\" width=\"83\" height=\"17\"/>\n                                        <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" alignment=\"right\" title=\"Video format:\" id=\"4pB-OE-3Z4\">\n                                            <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                            <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                            <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                        </textFieldCell>\n                                    </textField>\n                                    <button toolTip=\"Click for more information on Video Formats\" horizontalHuggingPriority=\"750\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"8lj-ap-GSr\">\n                                        <rect key=\"frame\" x=\"447\" y=\"555\" width=\"35\" height=\"35\"/>\n                                        <buttonCell key=\"cell\" type=\"help\" bezelStyle=\"helpButton\" alignment=\"center\" controlSize=\"large\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"ihk-vz-2UX\">\n                                            <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                                            <font key=\"font\" metaFont=\"system\"/>\n                                        </buttonCell>\n                                        <connections>\n                                            <action selector=\"helpVideoFormat:\" target=\"-2\" id=\"hYL-8G-pcH\"/>\n                                        </connections>\n                                    </button>\n                                    <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"TWt-lq-74o\">\n                                        <rect key=\"frame\" x=\"240\" y=\"174\" width=\"72\" height=\"17\"/>\n                                        <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" alignment=\"right\" title=\"Language:\" id=\"wbl-fa-ZtS\">\n                                            <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                            <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                            <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                        </textFieldCell>\n                                    </textField>\n                                    <box verticalHuggingPriority=\"750\" boxType=\"separator\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"vm9-LJ-GN6\">\n                                        <rect key=\"frame\" x=\"20\" y=\"110\" width=\"769\" height=\"5\"/>\n                                    </box>\n                                    <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"lzR-yN-m5b\">\n                                        <rect key=\"frame\" x=\"312\" y=\"19\" width=\"163\" height=\"40\"/>\n                                        <buttonCell key=\"cell\" type=\"push\" title=\"Reset All Settings\" bezelStyle=\"rounded\" image=\"NSRefreshTemplate\" imagePosition=\"leading\" alignment=\"center\" controlSize=\"large\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"T6y-Do-kQ7\">\n                                            <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                                            <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                        </buttonCell>\n                                        <connections>\n                                            <action selector=\"resetAllSettings:\" target=\"-2\" id=\"hnc-p1-Gd0\"/>\n                                        </connections>\n                                    </button>\n                                    <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"vYi-Hf-cI5\">\n                                        <rect key=\"frame\" x=\"475\" y=\"19\" width=\"183\" height=\"40\"/>\n                                        <buttonCell key=\"cell\" type=\"push\" title=\"Launch Setup Again\" bezelStyle=\"rounded\" image=\"aspectratio\" catalog=\"system\" imagePosition=\"left\" alignment=\"center\" controlSize=\"large\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"Bde-5x-OV2\">\n                                            <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                                            <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                        </buttonCell>\n                                        <connections>\n                                            <action selector=\"launchSetupAgainClick:\" target=\"-2\" id=\"ezf-Eb-gEI\"/>\n                                        </connections>\n                                    </button>\n                                    <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"D6x-HI-azM\">\n                                        <rect key=\"frame\" x=\"315\" y=\"285.5\" width=\"218\" height=\"22\"/>\n                                        <buttonCell key=\"cell\" type=\"check\" title=\"Autoplay previews in settings\" bezelStyle=\"regularSquare\" imagePosition=\"left\" controlSize=\"large\" state=\"on\" inset=\"2\" id=\"Nwj-gh-gOs\">\n                                            <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                                            <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                        </buttonCell>\n                                        <connections>\n                                            <action selector=\"autoPlaysPreviewsClick:\" target=\"-2\" id=\"sSe-40-4S5\"/>\n                                        </connections>\n                                    </button>\n                                    <button toolTip=\"If you have a vertical screen, and add your own vertical videos, checking this box will only play those on your vertical screen\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"oe5-rQ-KJu\">\n                                        <rect key=\"frame\" x=\"315\" y=\"396.5\" width=\"351\" height=\"22\"/>\n                                        <buttonCell key=\"cell\" type=\"check\" title=\"Play vertical videos if available on vertical screens\" bezelStyle=\"regularSquare\" imagePosition=\"left\" controlSize=\"large\" state=\"on\" inset=\"2\" id=\"CBO-Vx-vdy\">\n                                            <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                                            <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                        </buttonCell>\n                                        <connections>\n                                            <action selector=\"favorOrientationClick:\" target=\"-2\" id=\"FvZ-aY-Uqe\"/>\n                                        </connections>\n                                    </button>\n                                    <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"aZ7-cT-Z3Y\">\n                                        <rect key=\"frame\" x=\"315\" y=\"470.5\" width=\"436\" height=\"22\"/>\n                                        <buttonCell key=\"cell\" type=\"check\" title=\"Retina text support (may cause your fans to spin on Intel Macs)\" bezelStyle=\"regularSquare\" imagePosition=\"left\" controlSize=\"large\" state=\"on\" inset=\"2\" id=\"caS-lB-lS3\">\n                                            <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                                            <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                        </buttonCell>\n                                        <connections>\n                                            <action selector=\"highQualityTextClick:\" target=\"-2\" id=\"sph-zs-yx2\"/>\n                                        </connections>\n                                    </button>\n                                    <button toolTip=\"Built in videos don't have sound, but your local videos may have\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"xqc-uN-D8Z\">\n                                        <rect key=\"frame\" x=\"315\" y=\"322.5\" width=\"185\" height=\"22\"/>\n                                        <buttonCell key=\"cell\" type=\"check\" title=\"Mute all macOS sounds \" bezelStyle=\"regularSquare\" imagePosition=\"left\" controlSize=\"large\" state=\"on\" inset=\"2\" id=\"NR5-1m-1M0\">\n                                            <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                                            <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                        </buttonCell>\n                                        <constraints>\n                                            <constraint firstAttribute=\"width\" constant=\"182\" id=\"9dy-qP-jAn\"/>\n                                        </constraints>\n                                        <connections>\n                                            <action selector=\"muteAllMacOSSoundsClick:\" target=\"-2\" id=\"tPN-2g-idV\"/>\n                                        </connections>\n                                    </button>\n                                    <button toolTip=\"Enable this if you are using inverted colors in macOS accessibility settings\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"NT3-XE-JxM\">\n                                        <rect key=\"frame\" x=\"494\" y=\"566\" width=\"105\" height=\"22\"/>\n                                        <buttonCell key=\"cell\" type=\"check\" title=\"Invert colors\" bezelStyle=\"regularSquare\" imagePosition=\"left\" controlSize=\"large\" inset=\"2\" id=\"lwf-FQ-mER\">\n                                            <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                                            <font key=\"font\" metaFont=\"system\"/>\n                                        </buttonCell>\n                                        <connections>\n                                            <action selector=\"invertColorsCheckboxClick:\" target=\"-2\" id=\"aya-Dl-Uti\"/>\n                                        </connections>\n                                    </button>\n                                </subviews>\n                                <constraints>\n                                    <constraint firstItem=\"xqc-uN-D8Z\" firstAttribute=\"centerX\" secondItem=\"c2Y-BQ-Mg9\" secondAttribute=\"centerX\" id=\"18W-Sd-zDg\"/>\n                                    <constraint firstItem=\"ueZ-L1-tKm\" firstAttribute=\"leading\" secondItem=\"TLS-nM-OqY\" secondAttribute=\"leading\" constant=\"318\" id=\"2du-ua-F9P\"/>\n                                    <constraint firstItem=\"xFh-dw-fup\" firstAttribute=\"top\" secondItem=\"39U-7I-fEm\" secondAttribute=\"bottom\" constant=\"15\" id=\"31H-kh-2K3\"/>\n                                    <constraint firstItem=\"tVO-Se-9Jo\" firstAttribute=\"leading\" secondItem=\"TLS-nM-OqY\" secondAttribute=\"leading\" constant=\"318\" id=\"4V4-C7-nck\"/>\n                                    <constraint firstItem=\"lzR-yN-m5b\" firstAttribute=\"top\" secondItem=\"Jfm-Hl-4bN\" secondAttribute=\"bottom\" constant=\"20\" symbolic=\"YES\" id=\"5R9-xG-J2v\"/>\n                                    <constraint firstItem=\"oe5-rQ-KJu\" firstAttribute=\"top\" secondItem=\"4zW-Lf-b41\" secondAttribute=\"bottom\" constant=\"20\" id=\"6W7-eK-3i7\"/>\n                                    <constraint firstItem=\"tVO-Se-9Jo\" firstAttribute=\"leading\" secondItem=\"iIR-49-5le\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"8TE-Oa-fJN\"/>\n                                    <constraint firstItem=\"NT3-XE-JxM\" firstAttribute=\"leading\" secondItem=\"8lj-ap-GSr\" secondAttribute=\"trailing\" constant=\"20\" id=\"8YE-Mk-MW1\"/>\n                                    <constraint firstItem=\"Dka-WL-c4U\" firstAttribute=\"leading\" secondItem=\"Jfm-Hl-4bN\" secondAttribute=\"trailing\" constant=\"54\" id=\"8n9-hA-Z8p\"/>\n                                    <constraint firstItem=\"4zW-Lf-b41\" firstAttribute=\"top\" secondItem=\"aZ7-cT-Z3Y\" secondAttribute=\"bottom\" constant=\"20\" id=\"AS5-tg-40M\"/>\n                                    <constraint firstItem=\"ueZ-L1-tKm\" firstAttribute=\"leading\" secondItem=\"XVw-x2-MRK\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"AYE-8M-CZS\"/>\n                                    <constraint firstAttribute=\"height\" constant=\"610\" id=\"D6W-pg-TO3\"/>\n                                    <constraint firstItem=\"ueZ-L1-tKm\" firstAttribute=\"top\" secondItem=\"D6x-HI-azM\" secondAttribute=\"bottom\" constant=\"20\" id=\"FRj-RH-JJU\"/>\n                                    <constraint firstItem=\"geu-ZX-2ke\" firstAttribute=\"centerY\" secondItem=\"ueZ-L1-tKm\" secondAttribute=\"centerY\" id=\"Fy2-tC-HKo\"/>\n                                    <constraint firstItem=\"2PZ-3t-5f8\" firstAttribute=\"leading\" secondItem=\"TLS-nM-OqY\" secondAttribute=\"leading\" constant=\"318\" id=\"Gco-J1-0tC\"/>\n                                    <constraint firstItem=\"xqc-uN-D8Z\" firstAttribute=\"top\" secondItem=\"c2Y-BQ-Mg9\" secondAttribute=\"bottom\" constant=\"20\" id=\"H0J-LX-D0K\"/>\n                                    <constraint firstItem=\"ueZ-L1-tKm\" firstAttribute=\"firstBaseline\" secondItem=\"XVw-x2-MRK\" secondAttribute=\"firstBaseline\" id=\"IwS-Je-v70\"/>\n                                    <constraint firstItem=\"geu-ZX-2ke\" firstAttribute=\"leading\" secondItem=\"ueZ-L1-tKm\" secondAttribute=\"trailing\" constant=\"12\" symbolic=\"YES\" id=\"LrG-2R-86Y\"/>\n                                    <constraint firstItem=\"39U-7I-fEm\" firstAttribute=\"firstBaseline\" secondItem=\"TWt-lq-74o\" secondAttribute=\"firstBaseline\" id=\"Mf7-pV-7hz\"/>\n                                    <constraint firstItem=\"4zW-Lf-b41\" firstAttribute=\"leading\" secondItem=\"TLS-nM-OqY\" secondAttribute=\"leading\" constant=\"318\" id=\"Ndl-UR-fu3\"/>\n                                    <constraint firstItem=\"2PZ-3t-5f8\" firstAttribute=\"leading\" secondItem=\"XOJ-kW-rZe\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"OnU-nq-3Mq\"/>\n                                    <constraint firstItem=\"39U-7I-fEm\" firstAttribute=\"leading\" secondItem=\"TLS-nM-OqY\" secondAttribute=\"leading\" constant=\"318\" id=\"Puj-Eb-j5y\"/>\n                                    <constraint firstItem=\"Jfm-Hl-4bN\" firstAttribute=\"leading\" secondItem=\"TLS-nM-OqY\" secondAttribute=\"leading\" constant=\"318\" id=\"Q1j-2P-VDn\"/>\n                                    <constraint firstItem=\"vm9-LJ-GN6\" firstAttribute=\"leading\" secondItem=\"TLS-nM-OqY\" secondAttribute=\"leading\" constant=\"20\" symbolic=\"YES\" id=\"QaS-CI-PEw\"/>\n                                    <constraint firstItem=\"c2Y-BQ-Mg9\" firstAttribute=\"leading\" secondItem=\"TLS-nM-OqY\" secondAttribute=\"leading\" constant=\"318\" id=\"RKk-FA-9uw\"/>\n                                    <constraint firstItem=\"D6x-HI-azM\" firstAttribute=\"top\" secondItem=\"xqc-uN-D8Z\" secondAttribute=\"bottom\" constant=\"20\" id=\"Rrw-Ig-cEf\"/>\n                                    <constraint firstItem=\"aZ7-cT-Z3Y\" firstAttribute=\"top\" secondItem=\"2PZ-3t-5f8\" secondAttribute=\"bottom\" constant=\"22\" id=\"S2S-M3-zCB\"/>\n                                    <constraint firstItem=\"vYi-Hf-cI5\" firstAttribute=\"leading\" secondItem=\"lzR-yN-m5b\" secondAttribute=\"trailing\" constant=\"12\" symbolic=\"YES\" id=\"S9f-Ba-nxK\"/>\n                                    <constraint firstItem=\"4zW-Lf-b41\" firstAttribute=\"leading\" secondItem=\"aZ7-cT-Z3Y\" secondAttribute=\"leading\" id=\"TFC-3E-bHV\"/>\n                                    <constraint firstItem=\"Dka-WL-c4U\" firstAttribute=\"firstBaseline\" secondItem=\"Jfm-Hl-4bN\" secondAttribute=\"firstBaseline\" id=\"U3P-Nl-7RG\"/>\n                                    <constraint firstItem=\"tVO-Se-9Jo\" firstAttribute=\"top\" secondItem=\"TLS-nM-OqY\" secondAttribute=\"top\" constant=\"20\" id=\"UGH-UO-phS\"/>\n                                    <constraint firstItem=\"Jfm-Hl-4bN\" firstAttribute=\"top\" secondItem=\"vm9-LJ-GN6\" secondAttribute=\"bottom\" constant=\"22\" id=\"V6H-OP-zNH\"/>\n                                    <constraint firstItem=\"39U-7I-fEm\" firstAttribute=\"leading\" secondItem=\"TWt-lq-74o\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"VDt-Fb-vj7\"/>\n                                    <constraint firstItem=\"LK9-Dp-4je\" firstAttribute=\"top\" secondItem=\"ueZ-L1-tKm\" secondAttribute=\"bottom\" constant=\"22\" id=\"Y0k-HV-ymr\"/>\n                                    <constraint firstItem=\"xFh-dw-fup\" firstAttribute=\"leading\" secondItem=\"TLS-nM-OqY\" secondAttribute=\"leading\" constant=\"318\" id=\"YpY-4H-bmB\"/>\n                                    <constraint firstItem=\"2PZ-3t-5f8\" firstAttribute=\"firstBaseline\" secondItem=\"XOJ-kW-rZe\" secondAttribute=\"firstBaseline\" id=\"ZIP-Lp-oBA\"/>\n                                    <constraint firstItem=\"D6x-HI-azM\" firstAttribute=\"leading\" secondItem=\"c2Y-BQ-Mg9\" secondAttribute=\"leading\" id=\"d69-7p-N5D\"/>\n                                    <constraint firstItem=\"xqc-uN-D8Z\" firstAttribute=\"leading\" secondItem=\"c2Y-BQ-Mg9\" secondAttribute=\"leading\" id=\"dyP-Ph-BD4\"/>\n                                    <constraint firstItem=\"8lj-ap-GSr\" firstAttribute=\"centerY\" secondItem=\"tVO-Se-9Jo\" secondAttribute=\"centerY\" id=\"eN7-IJ-hRs\"/>\n                                    <constraint firstItem=\"tVO-Se-9Jo\" firstAttribute=\"firstBaseline\" secondItem=\"iIR-49-5le\" secondAttribute=\"firstBaseline\" id=\"gox-MD-zsu\"/>\n                                    <constraint firstItem=\"vm9-LJ-GN6\" firstAttribute=\"top\" secondItem=\"xFh-dw-fup\" secondAttribute=\"bottom\" constant=\"22\" id=\"iOb-2A-mIE\"/>\n                                    <constraint firstItem=\"c2Y-BQ-Mg9\" firstAttribute=\"top\" secondItem=\"oe5-rQ-KJu\" secondAttribute=\"bottom\" constant=\"20\" id=\"jD9-be-4VL\"/>\n                                    <constraint firstAttribute=\"trailing\" secondItem=\"vm9-LJ-GN6\" secondAttribute=\"trailing\" constant=\"20\" symbolic=\"YES\" id=\"n2a-VF-PSL\"/>\n                                    <constraint firstItem=\"2PZ-3t-5f8\" firstAttribute=\"top\" secondItem=\"tVO-Se-9Jo\" secondAttribute=\"bottom\" constant=\"22\" id=\"nnZ-3a-oB4\"/>\n                                    <constraint firstItem=\"8lj-ap-GSr\" firstAttribute=\"leading\" secondItem=\"tVO-Se-9Jo\" secondAttribute=\"trailing\" constant=\"12\" id=\"oHW-az-0fH\"/>\n                                    <constraint firstAttribute=\"trailing\" secondItem=\"LK9-Dp-4je\" secondAttribute=\"trailing\" constant=\"20\" symbolic=\"YES\" id=\"onr-sK-a8L\"/>\n                                    <constraint firstItem=\"LK9-Dp-4je\" firstAttribute=\"leading\" secondItem=\"TLS-nM-OqY\" secondAttribute=\"leading\" constant=\"20\" symbolic=\"YES\" id=\"pOS-5p-vmq\"/>\n                                    <constraint firstItem=\"NT3-XE-JxM\" firstAttribute=\"firstBaseline\" secondItem=\"iIR-49-5le\" secondAttribute=\"firstBaseline\" id=\"q8I-Tk-0kw\"/>\n                                    <constraint firstItem=\"oe5-rQ-KJu\" firstAttribute=\"leading\" secondItem=\"4zW-Lf-b41\" secondAttribute=\"leading\" id=\"qPY-ht-VCC\"/>\n                                    <constraint firstItem=\"vYi-Hf-cI5\" firstAttribute=\"firstBaseline\" secondItem=\"lzR-yN-m5b\" secondAttribute=\"firstBaseline\" id=\"upu-g3-3Ld\"/>\n                                    <constraint firstItem=\"lzR-yN-m5b\" firstAttribute=\"leading\" secondItem=\"Jfm-Hl-4bN\" secondAttribute=\"leading\" id=\"wZl-Er-mrV\"/>\n                                    <constraint firstItem=\"39U-7I-fEm\" firstAttribute=\"top\" secondItem=\"LK9-Dp-4je\" secondAttribute=\"bottom\" constant=\"22\" id=\"xRC-lU-F6I\"/>\n                                </constraints>\n                            </customView>\n                        </subviews>\n                        <constraints>\n                            <constraint firstAttribute=\"trailing\" secondItem=\"TLS-nM-OqY\" secondAttribute=\"trailing\" id=\"ELc-94-wBK\"/>\n                            <constraint firstItem=\"TLS-nM-OqY\" firstAttribute=\"top\" secondItem=\"EPP-mS-BQX\" secondAttribute=\"top\" id=\"H5y-4A-Spj\"/>\n                            <constraint firstItem=\"TLS-nM-OqY\" firstAttribute=\"leading\" secondItem=\"EPP-mS-BQX\" secondAttribute=\"leading\" id=\"khq-kf-q7Z\"/>\n                        </constraints>\n                    </clipView>\n                    <scroller key=\"horizontalScroller\" wantsLayer=\"YES\" verticalHuggingPriority=\"750\" horizontal=\"YES\" id=\"lDZ-9J-IhM\">\n                        <rect key=\"frame\" x=\"1\" y=\"646\" width=\"809\" height=\"16\"/>\n                        <autoresizingMask key=\"autoresizingMask\"/>\n                    </scroller>\n                    <scroller key=\"verticalScroller\" wantsLayer=\"YES\" verticalHuggingPriority=\"750\" doubleValue=\"1\" horizontal=\"NO\" id=\"68Y-fx-VNM\">\n                        <rect key=\"frame\" x=\"794\" y=\"1\" width=\"16\" height=\"661\"/>\n                        <autoresizingMask key=\"autoresizingMask\"/>\n                    </scroller>\n                </scrollView>\n            </subviews>\n            <constraints>\n                <constraint firstItem=\"yjL-IP-0lB\" firstAttribute=\"leading\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"leading\" id=\"3TR-0S-bRI\"/>\n                <constraint firstAttribute=\"trailing\" secondItem=\"yjL-IP-0lB\" secondAttribute=\"trailing\" id=\"4Am-Af-3hg\"/>\n                <constraint firstItem=\"yjL-IP-0lB\" firstAttribute=\"top\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"top\" id=\"89M-Yo-n8s\"/>\n                <constraint firstAttribute=\"height\" relation=\"greaterThanOrEqual\" constant=\"530\" id=\"SOi-hw-i2H\"/>\n                <constraint firstAttribute=\"trailing\" secondItem=\"6Ha-9D-VMf\" secondAttribute=\"trailing\" id=\"Uso-hM-AE1\"/>\n                <constraint firstItem=\"6Ha-9D-VMf\" firstAttribute=\"leading\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"leading\" id=\"frS-XR-hBo\"/>\n                <constraint firstAttribute=\"width\" relation=\"greaterThanOrEqual\" constant=\"811\" id=\"vRh-gY-tbC\"/>\n                <constraint firstItem=\"6Ha-9D-VMf\" firstAttribute=\"top\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"top\" constant=\"52\" id=\"x9a-eL-C0V\"/>\n                <constraint firstAttribute=\"bottom\" secondItem=\"6Ha-9D-VMf\" secondAttribute=\"bottom\" id=\"yNI-0k-oeK\"/>\n            </constraints>\n            <point key=\"canvasLocation\" x=\"-92.5\" y=\"279.5\"/>\n        </customView>\n        <viewController id=\"d0b-m7-AaQ\" userLabel=\"Popover View Controller\">\n            <connections>\n                <outlet property=\"view\" destination=\"QA9-SA-hku\" id=\"jEX-Qf-FNO\"/>\n            </connections>\n        </viewController>\n        <popover behavior=\"t\" id=\"Tj3-h3-vJZ\">\n            <connections>\n                <outlet property=\"contentViewController\" destination=\"d0b-m7-AaQ\" id=\"9Bw-pn-ei4\"/>\n            </connections>\n        </popover>\n        <viewController id=\"8DR-c7-V3C\" userLabel=\"Popover View Controller\">\n            <connections>\n                <outlet property=\"view\" destination=\"idy-Zq-5gl\" id=\"d9i-xF-SC8\"/>\n            </connections>\n        </viewController>\n        <popover behavior=\"t\" id=\"r9v-NK-gTh\">\n            <connections>\n                <outlet property=\"contentViewController\" destination=\"8DR-c7-V3C\" id=\"ts8-Na-Evf\"/>\n            </connections>\n        </popover>\n        <customView translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"idy-Zq-5gl\" userLabel=\"Power saving popover\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"334\" height=\"211\"/>\n            <subviews>\n                <textField focusRingType=\"none\" verticalHuggingPriority=\"750\" horizontalCompressionResistancePriority=\"250\" preferredMaxLayoutWidth=\"265\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"sau-H8-etT\">\n                    <rect key=\"frame\" x=\"18\" y=\"29\" width=\"298\" height=\"154\"/>\n                    <textFieldCell key=\"cell\" selectable=\"YES\" id=\"tDx-U1-0Sz\">\n                        <font key=\"font\" metaFont=\"message\" size=\"11\"/>\n                        <string key=\"title\">Aerial uses GPU hardware acceleration to reduce power consumption.\n\nYou can still decide to disable Aerial when running on battery, or if your battery is low (&lt;20%). If you enable one of those settings, Aerial will show a black screen and reduce your screen brightness to maximize power savings. \n\nYour screen brightness will be automatically restored on waking up. </string>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n            </subviews>\n            <constraints>\n                <constraint firstItem=\"sau-H8-etT\" firstAttribute=\"leading\" secondItem=\"idy-Zq-5gl\" secondAttribute=\"leading\" constant=\"20\" symbolic=\"YES\" id=\"BkA-t8-UQR\"/>\n                <constraint firstItem=\"sau-H8-etT\" firstAttribute=\"top\" secondItem=\"idy-Zq-5gl\" secondAttribute=\"top\" constant=\"28\" id=\"NU4-Mk-bGk\"/>\n                <constraint firstAttribute=\"trailing\" secondItem=\"sau-H8-etT\" secondAttribute=\"trailing\" constant=\"20\" symbolic=\"YES\" id=\"TVs-Be-54V\"/>\n                <constraint firstAttribute=\"bottom\" secondItem=\"sau-H8-etT\" secondAttribute=\"bottom\" constant=\"29\" id=\"urV-jC-VKG\"/>\n            </constraints>\n            <point key=\"canvasLocation\" x=\"684\" y=\"105.5\"/>\n        </customView>\n        <customView id=\"QA9-SA-hku\" userLabel=\"HW Acceleration popover\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"452\" height=\"405\"/>\n            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n            <subviews>\n                <textField focusRingType=\"none\" verticalHuggingPriority=\"750\" horizontalCompressionResistancePriority=\"250\" fixedFrame=\"YES\" preferredMaxLayoutWidth=\"334\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"fhD-YW-5Jq\">\n                    <rect key=\"frame\" x=\"18\" y=\"189\" width=\"416\" height=\"196\"/>\n                    <autoresizingMask key=\"autoresizingMask\"/>\n                    <textFieldCell key=\"cell\" selectable=\"YES\" refusesFirstResponder=\"YES\" id=\"pBv-Hh-hGu\">\n                        <font key=\"font\" metaFont=\"message\" size=\"11\"/>\n                        <string key=\"title\">The most appropriate format depends on your Mac. Video playback on macOS can be accelerated by your GPU.\n\n- Macs 2017 and newer should either use 1080p HEVC or 4K HEVC.\n\n- Late 2015/2016 Macs may only partially support hardware accelerated HEVC decoding. You may see higher CPU usage with these formats.\n\n- Macs older than late 2015 should prefer 1080p H264 as they may lack HEVC hardware decoding support.\n\nHDR videos are encoded using Dolby Vision to represent a Higher Dynamic range of colors and lighting. These videos have wilder colors that may look unrealistic to some. HDR is only available starting with macOS Catalina.</string>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <button fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"a0S-Jv-7q3\">\n                    <rect key=\"frame\" x=\"28\" y=\"33\" width=\"16\" height=\"18\"/>\n                    <autoresizingMask key=\"autoresizingMask\"/>\n                    <buttonCell key=\"cell\" type=\"square\" bezelStyle=\"shadowlessSquare\" image=\"NSStatusAvailable\" imagePosition=\"only\" alignment=\"center\" refusesFirstResponder=\"YES\" imageScaling=\"proportionallyUpOrDown\" inset=\"2\" id=\"caN-8Q-Cfo\">\n                        <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\"/>\n                    </buttonCell>\n                </button>\n                <button fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Suq-Wx-2D8\">\n                    <rect key=\"frame\" x=\"28\" y=\"13\" width=\"16\" height=\"18\"/>\n                    <autoresizingMask key=\"autoresizingMask\"/>\n                    <buttonCell key=\"cell\" type=\"square\" bezelStyle=\"shadowlessSquare\" image=\"NSStatusPartiallyAvailable\" imagePosition=\"only\" alignment=\"center\" refusesFirstResponder=\"YES\" imageScaling=\"proportionallyUpOrDown\" inset=\"2\" id=\"kM4-Rc-Xiy\">\n                        <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\"/>\n                    </buttonCell>\n                </button>\n                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"nz2-xT-PMG\">\n                    <rect key=\"frame\" x=\"50\" y=\"15\" width=\"314\" height=\"14\"/>\n                    <autoresizingMask key=\"autoresizingMask\"/>\n                    <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" refusesFirstResponder=\"YES\" title=\"HEVC acceleration may be supported\" id=\"Tiu-80-XDP\">\n                        <font key=\"font\" metaFont=\"message\" size=\"11\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Txl-g4-G2k\">\n                    <rect key=\"frame\" x=\"50\" y=\"35\" width=\"314\" height=\"14\"/>\n                    <autoresizingMask key=\"autoresizingMask\"/>\n                    <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" refusesFirstResponder=\"YES\" title=\"H.264 acceleration is supported\" id=\"XzM-zr-fcM\">\n                        <font key=\"font\" metaFont=\"message\" size=\"11\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <imageView horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"WRc-cq-5rf\">\n                    <rect key=\"frame\" x=\"20\" y=\"123\" width=\"24\" height=\"24\"/>\n                    <autoresizingMask key=\"autoresizingMask\"/>\n                    <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" image=\"NSCaution\" id=\"Tjk-u2-njs\"/>\n                </imageView>\n                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" fixedFrame=\"YES\" preferredMaxLayoutWidth=\"319\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"4zF-9T-BaK\">\n                    <rect key=\"frame\" x=\"50\" y=\"87\" width=\"384\" height=\"61\"/>\n                    <autoresizingMask key=\"autoresizingMask\"/>\n                    <textFieldCell key=\"cell\" refusesFirstResponder=\"YES\" id=\"vza-qo-Tcb\">\n                        <font key=\"font\" metaFont=\"message\" size=\"11\"/>\n                        <string key=\"title\">Please note that not every video is available in every format. Older videos may not be available in 4K, and some newer videos are not available in 1080 H.264. Aerial will try to play the best format available based on your choice.</string>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <button verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"lF6-k7-1O1\">\n                    <rect key=\"frame\" x=\"59\" y=\"57\" width=\"334\" height=\"25\"/>\n                    <autoresizingMask key=\"autoresizingMask\"/>\n                    <buttonCell key=\"cell\" type=\"bevel\" title=\"More information is available on our project page\" bezelStyle=\"rounded\" alignment=\"center\" refusesFirstResponder=\"YES\" inset=\"2\" id=\"tEp-LQ-x5Y\">\n                        <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" metaFont=\"message\" size=\"11\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"projectPageClick:\" target=\"-2\" id=\"VZw-dh-IWt\"/>\n                    </connections>\n                </button>\n                <button verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"6TF-Ix-bNE\">\n                    <rect key=\"frame\" x=\"59\" y=\"156\" width=\"334\" height=\"25\"/>\n                    <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMaxY=\"YES\"/>\n                    <buttonCell key=\"cell\" type=\"bevel\" title=\"More information about Dolby Vision on Wikipedia\" bezelStyle=\"rounded\" alignment=\"center\" refusesFirstResponder=\"YES\" inset=\"2\" id=\"xIY-HN-Ee0\">\n                        <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" metaFont=\"message\" size=\"11\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"dolbyVisionClick:\" target=\"-2\" id=\"SEr-ln-9bJ\"/>\n                    </connections>\n                </button>\n            </subviews>\n            <point key=\"canvasLocation\" x=\"743\" y=\"540\"/>\n        </customView>\n    </objects>\n    <resources>\n        <image name=\"NSCaution\" width=\"32\" height=\"32\"/>\n        <image name=\"NSFolder\" width=\"32\" height=\"32\"/>\n        <image name=\"NSRefreshTemplate\" width=\"18\" height=\"21\"/>\n        <image name=\"NSStatusAvailable\" width=\"16\" height=\"16\"/>\n        <image name=\"NSStatusPartiallyAvailable\" width=\"16\" height=\"16\"/>\n        <image name=\"aspectratio\" catalog=\"system\" width=\"18\" height=\"14\"/>\n        <image name=\"folder\" catalog=\"system\" width=\"18\" height=\"14\"/>\n        <image name=\"wrench.and.screwdriver\" catalog=\"system\" width=\"24\" height=\"23\"/>\n    </resources>\n</document>\n"
  },
  {
    "path": "Resources/MainUI/Settings panels/BrightnessViewController.swift",
    "content": "//\n//  BrightnessViewController.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 19/07/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Cocoa\n\nclass BrightnessViewController: NSViewController {\n\n    @IBOutlet var lowerBrightness: NSButton!\n\n    @IBOutlet var startFromSlider: NSSlider!\n    @IBOutlet var fadeToSlider: NSSlider!\n\n    @IBOutlet var sleepAfterLabel: NSTextField!\n\n    @IBOutlet var onlyDimAtNight: NSButton!\n    @IBOutlet var onlyDimOnBattery: NSButton!\n\n    var savedBrightness: Float?\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n\n        // Main switch\n        if PrefsDisplays.dimBrightness {\n            lowerBrightness.state = .on\n            changeBrightnessState(to: true)\n        } else {\n            changeBrightnessState(to: false)\n        }\n\n        startFromSlider.doubleValue = PrefsDisplays.startDim\n        fadeToSlider.doubleValue = PrefsDisplays.endDim\n\n        onlyDimAtNight.state = PrefsDisplays.dimOnlyAtNight ? .on : .off\n        onlyDimOnBattery.state = PrefsDisplays.dimOnlyAtNight ? .on : .off\n\n        DispatchQueue.main.async {\n            let sleepTime = TimeManagement.sharedInstance.getCurrentSleepTime()\n            if sleepTime != 0 {\n                self.sleepAfterLabel.stringValue = \"Your Mac currently goes to sleep after \\(sleepTime) minute\\(sleepTime != 1 ? \"s\" : \"\")\"\n            } else {\n                self.sleepAfterLabel.stringValue = \"Unable to determine your Mac sleep settings\"\n            }\n        }\n    }\n\n    func changeBrightnessState(to: Bool) {\n        onlyDimAtNight.isEnabled = to\n        onlyDimOnBattery.isEnabled = to\n        startFromSlider.isEnabled = to\n        fadeToSlider.isEnabled = to\n    }\n\n    @IBAction func lowerBrightnessClick(_ sender: NSButton) {\n        PrefsDisplays.dimBrightness = sender.state == .on\n        changeBrightnessState(to: sender.state == .on)\n\n    }\n\n    @IBAction func startFromSliderChange(_ sender: NSSliderCell) {\n        guard let event = NSApplication.shared.currentEvent else { return }\n\n        guard [.leftMouseUp, .leftMouseDown, .leftMouseDragged].contains(event.type) else {\n            return\n        }\n\n        if event.type == .leftMouseUp {\n            if let brightness = savedBrightness {\n                Brightness.set(level: brightness)\n                savedBrightness = nil\n            }\n            PrefsDisplays.startDim = sender.doubleValue\n        } else {\n            if savedBrightness == nil {\n                savedBrightness = Brightness.get()\n            }\n            Brightness.set(level: sender.floatValue)\n        }\n    }\n\n    @IBAction func fadeToSliderChange(_ sender: NSSliderCell) {\n        guard let event = NSApplication.shared.currentEvent else { return }\n\n        // Hmm\n        if ![.leftMouseUp, .leftMouseDown, .leftMouseDragged].contains(event.type) {\n        }\n\n        if event.type == .leftMouseUp {\n            if let brightness = savedBrightness {\n                Brightness.set(level: brightness)\n                savedBrightness = nil\n            }\n            PrefsDisplays.endDim = sender.doubleValue\n        } else {\n            if savedBrightness == nil {\n                savedBrightness = Brightness.get()\n            }\n            Brightness.set(level: sender.floatValue)\n        }\n    }\n    @IBAction func onlyDimAtNightClick(_ sender: NSButton) {\n        PrefsDisplays.dimOnlyAtNight = sender.state == .on\n    }\n    @IBAction func onlyDimOnBatteryClick(_ sender: NSButton) {\n        PrefsDisplays.dimOnlyOnBattery = sender.state == .on\n    }\n}\n"
  },
  {
    "path": "Resources/MainUI/Settings panels/BrightnessViewController.xib",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.Cocoa.XIB\" version=\"3.0\" toolsVersion=\"23094\" targetRuntime=\"MacOSX.Cocoa\" propertyAccessControl=\"none\" useAutolayout=\"YES\" customObjectInstantitationMethod=\"direct\">\n    <dependencies>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.CocoaPlugin\" version=\"23094\"/>\n        <capability name=\"Image references\" minToolsVersion=\"12.0\"/>\n        <capability name=\"System colors introduced in macOS 10.14\" minToolsVersion=\"10.0\"/>\n        <capability name=\"documents saved in the Xcode 8 format\" minToolsVersion=\"8.0\"/>\n    </dependencies>\n    <objects>\n        <customObject id=\"-2\" userLabel=\"File's Owner\" customClass=\"BrightnessViewController\" customModule=\"Aerial\" customModuleProvider=\"target\">\n            <connections>\n                <outlet property=\"fadeToSlider\" destination=\"gQf-ZQ-hsb\" id=\"i0H-fe-ouq\"/>\n                <outlet property=\"lowerBrightness\" destination=\"rTv-ct-a72\" id=\"Hzb-cQ-Bvl\"/>\n                <outlet property=\"onlyDimAtNight\" destination=\"MXe-aq-z27\" id=\"SkY-Ha-6ha\"/>\n                <outlet property=\"onlyDimOnBattery\" destination=\"E0D-Qf-cW9\" id=\"ZMC-Zn-v1k\"/>\n                <outlet property=\"sleepAfterLabel\" destination=\"NR2-tO-ywP\" id=\"4vP-XJ-5Un\"/>\n                <outlet property=\"startFromSlider\" destination=\"Zjp-n9-q99\" id=\"Hdc-nI-R1U\"/>\n                <outlet property=\"view\" destination=\"Hz6-mo-xeY\" id=\"0bl-1N-x8E\"/>\n            </connections>\n        </customObject>\n        <customObject id=\"-1\" userLabel=\"First Responder\" customClass=\"FirstResponder\"/>\n        <customObject id=\"-3\" userLabel=\"Application\" customClass=\"NSObject\"/>\n        <customView translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Hz6-mo-xeY\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"811\" height=\"530\"/>\n            <subviews>\n                <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"rTv-ct-a72\">\n                    <rect key=\"frame\" x=\"197\" y=\"450.5\" width=\"274\" height=\"22\"/>\n                    <string key=\"toolTip\">If enabled, Aerial will lower your screen brightness to your desired setting, and fade it progressively until your Mac goes to sleep</string>\n                    <buttonCell key=\"cell\" type=\"check\" title=\"Lower brightness while playing videos\" bezelStyle=\"regularSquare\" imagePosition=\"left\" controlSize=\"large\" inset=\"2\" id=\"kxF-VJ-OEL\">\n                        <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"lowerBrightnessClick:\" target=\"-2\" id=\"6aT-m2-P6M\"/>\n                    </connections>\n                </button>\n                <button toolTip=\"Check if you only want to enable the brightness dimming at night\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"MXe-aq-z27\">\n                    <rect key=\"frame\" x=\"197\" y=\"291.5\" width=\"212\" height=\"22\"/>\n                    <buttonCell key=\"cell\" type=\"check\" title=\"Only dim brightness at night\" bezelStyle=\"regularSquare\" imagePosition=\"left\" controlSize=\"large\" inset=\"2\" id=\"G4I-F0-Kzd\">\n                        <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"onlyDimAtNightClick:\" target=\"-2\" id=\"AvP-48-tp5\"/>\n                    </connections>\n                </button>\n                <button toolTip=\"Check if you only want to enable the brightness dimming when on battery\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"E0D-Qf-cW9\">\n                    <rect key=\"frame\" x=\"197\" y=\"252.5\" width=\"229\" height=\"22\"/>\n                    <buttonCell key=\"cell\" type=\"check\" title=\"Only dim brightness on battery\" bezelStyle=\"regularSquare\" imagePosition=\"left\" controlSize=\"large\" inset=\"2\" id=\"SLW-yU-xBg\">\n                        <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"onlyDimOnBatteryClick:\" target=\"-2\" id=\"18Y-1W-f3K\"/>\n                    </connections>\n                </button>\n                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"NR2-tO-ywP\">\n                    <rect key=\"frame\" x=\"198\" y=\"333\" width=\"4\" height=\"17\"/>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" id=\"Mjm-0D-ERr\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <slider verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Zjp-n9-q99\">\n                    <rect key=\"frame\" x=\"198\" y=\"405\" width=\"254\" height=\"28\"/>\n                    <constraints>\n                        <constraint firstAttribute=\"width\" constant=\"250\" id=\"36E-yk-7Ut\"/>\n                    </constraints>\n                    <sliderCell key=\"cell\" controlSize=\"large\" continuous=\"YES\" state=\"on\" alignment=\"left\" maxValue=\"1\" doubleValue=\"1\" tickMarkPosition=\"above\" numberOfTickMarks=\"5\" sliderType=\"linear\" id=\"lrx-Nh-yVE\"/>\n                    <connections>\n                        <action selector=\"startFromSliderChange:\" target=\"-2\" id=\"CMb-p5-yWb\"/>\n                    </connections>\n                </slider>\n                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"ek8-ut-oUM\">\n                    <rect key=\"frame\" x=\"120\" y=\"414\" width=\"74\" height=\"17\"/>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" title=\"Start from:\" id=\"rv9-0q-qqD\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <slider verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"gQf-ZQ-hsb\">\n                    <rect key=\"frame\" x=\"198\" y=\"366\" width=\"254\" height=\"28\"/>\n                    <constraints>\n                        <constraint firstAttribute=\"width\" constant=\"250\" id=\"pzV-rb-8Bf\"/>\n                    </constraints>\n                    <sliderCell key=\"cell\" controlSize=\"large\" continuous=\"YES\" state=\"on\" alignment=\"left\" maxValue=\"1\" doubleValue=\"1\" tickMarkPosition=\"above\" numberOfTickMarks=\"5\" sliderType=\"linear\" id=\"PEJ-J7-U1S\"/>\n                    <connections>\n                        <action selector=\"fadeToSliderChange:\" target=\"-2\" id=\"WIo-7i-wcv\"/>\n                    </connections>\n                </slider>\n                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"eei-VX-faK\">\n                    <rect key=\"frame\" x=\"137\" y=\"375\" width=\"57\" height=\"17\"/>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" title=\"Fade to:\" id=\"uHK-Ny-zuZ\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <imageView horizontalHuggingPriority=\"25\" verticalHuggingPriority=\"25\" horizontalCompressionResistancePriority=\"75\" verticalCompressionResistancePriority=\"75\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"1kt-MQ-sfT\">\n                    <rect key=\"frame\" x=\"16\" y=\"481\" width=\"28.5\" height=\"45\"/>\n                    <constraints>\n                        <constraint firstAttribute=\"height\" constant=\"34\" id=\"5Fh-5p-q6e\"/>\n                        <constraint firstAttribute=\"width\" constant=\"28\" id=\"vON-4g-3J9\"/>\n                    </constraints>\n                    <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyUpOrDown\" id=\"ntL-Bj-5UG\">\n                        <imageReference key=\"image\" image=\"sun.min\" catalog=\"system\" symbolScale=\"large\"/>\n                    </imageCell>\n                    <color key=\"contentTintColor\" name=\"controlAccentColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                </imageView>\n                <textField focusRingType=\"none\" horizontalCompressionResistancePriority=\"250\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"egg-ke-irR\">\n                    <rect key=\"frame\" x=\"52\" y=\"497\" width=\"323\" height=\"17\"/>\n                    <textFieldCell key=\"cell\" selectable=\"YES\" title=\"Brightness control only works with Apple displays\" id=\"kxG-OU-XlP\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n            </subviews>\n            <constraints>\n                <constraint firstItem=\"1kt-MQ-sfT\" firstAttribute=\"leading\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"leading\" constant=\"16\" id=\"1LD-kO-PJh\"/>\n                <constraint firstItem=\"egg-ke-irR\" firstAttribute=\"leading\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"leading\" constant=\"54\" id=\"8ai-jg-xw5\"/>\n                <constraint firstItem=\"rTv-ct-a72\" firstAttribute=\"leading\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"leading\" constant=\"200\" id=\"BNx-o2-9C2\"/>\n                <constraint firstItem=\"NR2-tO-ywP\" firstAttribute=\"top\" secondItem=\"gQf-ZQ-hsb\" secondAttribute=\"bottom\" constant=\"22\" id=\"CPh-k4-TCP\"/>\n                <constraint firstItem=\"MXe-aq-z27\" firstAttribute=\"leading\" secondItem=\"rTv-ct-a72\" secondAttribute=\"leading\" id=\"Ix6-zz-1ID\"/>\n                <constraint firstItem=\"gQf-ZQ-hsb\" firstAttribute=\"firstBaseline\" secondItem=\"eei-VX-faK\" secondAttribute=\"firstBaseline\" id=\"PKu-cX-kOM\"/>\n                <constraint firstItem=\"MXe-aq-z27\" firstAttribute=\"top\" secondItem=\"NR2-tO-ywP\" secondAttribute=\"bottom\" constant=\"22\" id=\"ROm-s0-lZ4\"/>\n                <constraint firstAttribute=\"width\" relation=\"greaterThanOrEqual\" constant=\"811\" id=\"RRk-SS-lUC\"/>\n                <constraint firstAttribute=\"height\" relation=\"greaterThanOrEqual\" constant=\"530\" id=\"RmM-Qs-DF8\"/>\n                <constraint firstItem=\"E0D-Qf-cW9\" firstAttribute=\"top\" secondItem=\"MXe-aq-z27\" secondAttribute=\"bottom\" constant=\"22\" id=\"bpJ-kA-ASb\"/>\n                <constraint firstItem=\"Zjp-n9-q99\" firstAttribute=\"leading\" secondItem=\"ek8-ut-oUM\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"eLX-Fd-iZi\"/>\n                <constraint firstItem=\"Zjp-n9-q99\" firstAttribute=\"firstBaseline\" secondItem=\"ek8-ut-oUM\" secondAttribute=\"firstBaseline\" id=\"g2a-t0-dpw\"/>\n                <constraint firstItem=\"egg-ke-irR\" firstAttribute=\"top\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"top\" constant=\"16\" id=\"gHc-6I-5dj\"/>\n                <constraint firstItem=\"1kt-MQ-sfT\" firstAttribute=\"top\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"top\" constant=\"10\" id=\"gsD-02-yAL\"/>\n                <constraint firstItem=\"NR2-tO-ywP\" firstAttribute=\"leading\" secondItem=\"rTv-ct-a72\" secondAttribute=\"leading\" id=\"gza-i6-CJX\"/>\n                <constraint firstItem=\"gQf-ZQ-hsb\" firstAttribute=\"leading\" secondItem=\"rTv-ct-a72\" secondAttribute=\"leading\" id=\"nhC-wQ-I6y\"/>\n                <constraint firstItem=\"eei-VX-faK\" firstAttribute=\"top\" secondItem=\"ek8-ut-oUM\" secondAttribute=\"bottom\" constant=\"22\" id=\"q0c-nT-Hig\"/>\n                <constraint firstItem=\"rTv-ct-a72\" firstAttribute=\"top\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"top\" constant=\"60\" id=\"sDp-Dj-7MD\"/>\n                <constraint firstItem=\"ek8-ut-oUM\" firstAttribute=\"top\" secondItem=\"rTv-ct-a72\" secondAttribute=\"bottom\" constant=\"22\" id=\"sGA-HQ-2K0\"/>\n                <constraint firstItem=\"gQf-ZQ-hsb\" firstAttribute=\"leading\" secondItem=\"eei-VX-faK\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"sVL-X4-ZJj\"/>\n                <constraint firstItem=\"E0D-Qf-cW9\" firstAttribute=\"leading\" secondItem=\"rTv-ct-a72\" secondAttribute=\"leading\" id=\"vUM-qu-2Ql\"/>\n                <constraint firstItem=\"Zjp-n9-q99\" firstAttribute=\"leading\" secondItem=\"rTv-ct-a72\" secondAttribute=\"leading\" id=\"viO-g4-mvt\"/>\n            </constraints>\n            <point key=\"canvasLocation\" x=\"-172\" y=\"154\"/>\n        </customView>\n    </objects>\n    <resources>\n        <image name=\"sun.min\" catalog=\"system\" width=\"20\" height=\"20\"/>\n    </resources>\n</document>\n"
  },
  {
    "path": "Resources/MainUI/Settings panels/CacheViewController.swift",
    "content": "//\n//  CacheViewController.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 18/07/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Cocoa\n\nextension Double {\n    /// Rounds the double to decimal places value\n    func rounded(toPlaces places: Int) -> Double {\n        let divisor = pow(10.0, Double(places))\n        return (self * divisor).rounded() / divisor\n    }\n}\n\nclass CacheViewController: NSViewController {\n\n    @IBOutlet var automaticallyDownloadCheckbox: NSButton!\n\n    // We use two views for two available modes\n    @IBOutlet var automaticContainerView: NSView!\n    @IBOutlet var manualContainerView: NSView!\n\n    @IBOutlet var limitSlider: NSSlider!\n    @IBOutlet var limitTextField: NSTextField!\n    @IBOutlet var limitLabel: NSTextField!\n    @IBOutlet var limitUnitLabel: NSTextField!\n\n    @IBOutlet var rotateFrequencyLabel: NSTextField!\n    @IBOutlet var rotateFrequencyPopup: NSPopUpButton!\n\n    @IBOutlet var restrictWiFiCheckbox: NSButton!\n\n    @IBOutlet var connectedIcon: NSButton!\n    @IBOutlet var connectedLabel: NSTextField!\n\n    @IBOutlet var addCurrentNetworkButton: NSButton!\n\n    @IBOutlet var resetListButton: NSButton!\n    @IBOutlet var allowedListLabel: NSTextField!\n\n    @IBOutlet var showDownloadIndicator: NSButton!\n\n    @IBOutlet var cacheBox: NSBox!\n    @IBOutlet var freeBox: NSBox!\n    @IBOutlet var packsBox: NSBox!\n\n    // Manual mode\n    @IBOutlet var cacheSize: NSTextField!\n    @IBOutlet var makeTimeMachineIgnore: NSButton!\n    @IBOutlet var makeTimeMachineIgnore2: NSButton!\n\n    @IBOutlet var manuallyPick: NSButton!\n    @IBOutlet var pickFolder: NSButton!\n    @IBOutlet var manuallyPickLabel: NSTextField!\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n\n        DispatchQueue.main.async {\n            self.makeTimeMachineIgnore.state = TimeMachine.isExcluded() ? .on : .off\n            self.makeTimeMachineIgnore2.state = self.makeTimeMachineIgnore.state\n            debugLog(\"tm : \\(self.makeTimeMachineIgnore.state)\")\n        }\n\n        manuallyPick.state = PrefsCache.overrideCache ? .on : .off\n        if #available(OSX 12, *) {\n            updateCachePath()\n        } else if #available(OSX 10.15, *) {\n            manuallyPick.isEnabled = false\n            pickFolder.isHidden = true\n        } else {\n            updateCachePath()\n        }\n\n        // Cache panel\n        automaticallyDownloadCheckbox.state = PrefsCache.enableManagement ? .on : .off\n\n        limitTextField.doubleValue = PrefsCache.cacheLimit\n        limitSlider.doubleValue = PrefsCache.cacheLimit\n        rotateFrequencyPopup.selectItem(at: PrefsCache.cachePeriodicity.rawValue)\n\n        // Update the size of the cache and associated controls\n        updateCacheSize()\n\n        // Wi-Fi restrictions?\n        restrictWiFiCheckbox.state = PrefsCache.restrictOnWiFi ? .on : .off\n        updateNetworkStatus()\n\n        // And the master switch!\n        updateCacheVisibility()\n\n        showDownloadIndicator.state = PrefsCache.showBackgroundDownloads ? .on : .off\n\n        updateCacheBox()\n    }\n\n    func updateCachePath() {\n        if PrefsCache.overrideCache {\n            // if let cachePath = Cache.supportPath {\n                manuallyPickLabel.stringValue = \"Using \\(Cache.supportPath)\"\n            /*} else {\n                manuallyPickLabel.stringValue = \"Select a path using the folder picker\"\n            }*/\n\n        } else {\n            manuallyPickLabel.stringValue = \"Using your Application Support directory\"\n        }\n    }\n\n    func updateCacheBox() {\n        let usedCache = Cache.size()\n        let packsSize = Cache.packsSize()\n\n        //print(\"pack size : \\(packsSize)\")\n\n        var maxCache = PrefsCache.cacheLimit\n        var freeCache = usedCache > maxCache ? 0 : maxCache - usedCache\n\n        if PrefsCache.cacheLimit == 101 || !PrefsCache.enableManagement {\n            freeCache = 0\n            maxCache = usedCache\n        }\n\n        // This is the total max usage, used to draw the bar\n        var totalPotentialSize = max(maxCache, usedCache) + packsSize\n        if totalPotentialSize == 0 {\n            totalPotentialSize = 1\n        }\n        // let totalUsage = usedCache\n\n        let cacheWidth = Int(usedCache * 486 / totalPotentialSize)\n        let freeWidth = Int(freeCache * 486 / totalPotentialSize)\n        let packsWidth = Int(packsSize * 486 / totalPotentialSize)\n        var cacheString = \"\"\n\n        if usedCache > 0 {\n            cacheString.append(\"\\(usedCache.rounded(toPlaces: 1)) GB used by cached videos\")\n            cacheBox.isHidden = false\n            cacheBox.frame.origin.x = CGFloat(206)   // We offset by 1px to make the borders overlap\n            cacheBox.setFrameSize(NSSize(width: cacheWidth, height: 25))\n        } else {\n            cacheString.append(\"No space used by cached videos\")\n            cacheBox.isHidden = true\n        }\n\n        if freeCache > 0 {\n            cacheString.append(\", \\(freeCache.rounded(toPlaces: 1)) GB remaining in your cache limit\")\n            freeBox.isHidden = false\n            freeBox.frame.origin.x = CGFloat(206 + cacheWidth - 1)   // We offset by 1px to make the borders overlap\n            freeBox.setFrameSize(NSSize(width: freeWidth, height: 25))\n        } else {\n            if PrefsCache.cacheLimit != 101 && PrefsCache.enableManagement {\n                cacheString.append(\", your cache is full!\")\n            }\n            freeBox.isHidden = true\n        }\n\n        if packsSize > 0.01 {\n            cacheString.append(\", \\(packsSize.rounded(toPlaces: 1)) GB used by packs\")\n            packsBox.isHidden = false\n            packsBox.frame.origin.x = CGFloat(206 + cacheWidth + freeWidth - 2)   // We offset by 1px to make the borders overlap\n            packsBox.setFrameSize(NSSize(width: packsWidth, height: 25))\n        } else {\n            packsBox.isHidden = true\n        }\n\n        // (8 GB for packs, 32 GB for the cache, still 8 GB of free cache available for more videos)\n\n        limitLabel.stringValue = cacheString\n    }\n\n    @IBAction func showDownloadIndicatorChange(_ sender: NSButton) {\n        PrefsCache.showBackgroundDownloads = sender.state == .on\n    }\n    @IBAction func automaticallyDownloadClick(_ sender: NSButton) {\n        PrefsCache.enableManagement = sender.state == .on\n        updateCacheVisibility()\n        updateCacheBox()\n    }\n\n    @IBAction func limitSliderChange(_ sender: NSSlider) {\n        PrefsCache.cacheLimit = sender.doubleValue.rounded(toPlaces: 1)\n        limitTextField.doubleValue = sender.doubleValue.rounded(toPlaces: 1)\n        updateCacheSize()\n        updateCacheBox()\n    }\n\n    @IBAction func limitTextFieldChange(_ sender: NSTextField) {\n        PrefsCache.cacheLimit = sender.doubleValue\n        limitSlider.doubleValue = sender.doubleValue\n    }\n\n    @IBAction func rotateFrequencyChange(_ sender: NSPopUpButton) {\n        PrefsCache.cachePeriodicity = CachePeriodicity(rawValue: sender.indexOfSelectedItem)!\n    }\n\n    @IBAction func restrictWiFiCheck(_ sender: NSButton) {\n        PrefsCache.restrictOnWiFi = sender.state == .on\n        updateNetworkStatus()\n    }\n\n    @IBAction func addCurrentNetworkClick(_ sender: Any) {\n        if !PrefsCache.allowedNetworks.contains(Cache.ssid) {\n            PrefsCache.allowedNetworks.append(Cache.ssid)\n        }\n        updateNetworkStatus()\n    }\n    @IBAction func resetListClick(_ sender: Any) {\n        PrefsCache.allowedNetworks.removeAll()\n        updateNetworkStatus()\n    }\n\n    // Helpers\n    func updateNetworkStatus() {\n        if PrefsCache.restrictOnWiFi {\n            connectedIcon.isHidden = false\n            connectedLabel.isHidden = false\n            addCurrentNetworkButton.isHidden = false\n            resetListButton.isHidden = false\n            allowedListLabel.isHidden = false\n        } else {\n            connectedIcon.isHidden = true\n            connectedLabel.isHidden = true\n            addCurrentNetworkButton.isHidden = true\n            resetListButton.isHidden = true\n            allowedListLabel.isHidden = true\n        }\n\n        connectedIcon.image = Cache.canNetwork() ?\n            NSImage(named: NSImage.statusAvailableName) :\n            NSImage(named: NSImage.statusUnavailableName)\n\n        if Cache.ssid != \"\" {\n            connectedLabel.stringValue = \"Connected to: \" + Cache.ssid + \" \" + (Cache.canNetwork() ? \"(trusted)\" : \"(restricted)\")\n        } else {\n            connectedLabel.stringValue = \"Not connected to Wi-Fi\"\n        }\n\n        if PrefsCache.allowedNetworks.isEmpty {\n            allowedListLabel.stringValue = \"No network currently allowed\"\n        } else {\n            allowedListLabel.stringValue = \"Allowed: \" + PrefsCache.allowedNetworks.joined(separator: \", \")\n        }\n    }\n\n    // Update UI depending on the master switch position\n    func updateCacheVisibility() {\n        if PrefsCache.enableManagement {\n            automaticContainerView.isHidden = false\n            manualContainerView.isHidden = true\n        } else {\n            automaticContainerView.isHidden = true\n            manualContainerView.isHidden = false\n        }\n    }\n\n    func updateCacheSize() {\n        let size = Cache.sizeString()\n\n        if PrefsCache.cacheLimit == 101 {\n            limitTextField.isHidden = true\n            limitUnitLabel.isHidden = true\n            rotateFrequencyPopup.isEnabled = false\n            rotateFrequencyLabel.isEnabled = false\n        } else {\n            limitTextField.isHidden = false\n            limitUnitLabel.isHidden = false\n            rotateFrequencyPopup.isEnabled = true\n            rotateFrequencyLabel.isEnabled = true\n        }\n\n        // limitLabel.stringValue = \"(Currently \\(size))\"\n        cacheSize.stringValue = \"Your videos take \\(size) of disk space\"\n    }\n\n    // Manual mode\n    @IBAction func showInFinderClick(_ sender: Any) {\n        NSWorkspace.shared.selectFile(nil, inFileViewerRootedAtPath: VideoCache.cacheDirectory!)\n    }\n\n    @IBAction func pickFolderButton(_ sender: Any) {\n        let openPanel = NSOpenPanel()\n\n        openPanel.canChooseDirectories = true\n        openPanel.canChooseFiles = false\n        openPanel.canCreateDirectories = true\n        openPanel.allowsMultipleSelection = false\n        openPanel.title = \"Choose Aerial Cache Directory\"\n        openPanel.prompt = \"Choose\"\n\n        // Grab the supportPath\n        if let customPath = PrefsCache.supportPath {\n            if customPath != \"\" {\n                openPanel.directoryURL = URL(fileURLWithPath: customPath)\n            }\n        }\n\n        openPanel.begin { result in\n            guard result.rawValue == NSFileHandlingPanelOKButton, !openPanel.urls.isEmpty else {\n                return\n            }\n\n            let cacheDirectory = openPanel.urls[0]\n            PrefsCache.supportPath = cacheDirectory.path\n\n            // On macOS 12 we save a security scoped bookmark\n            if #available(macOS 12, *) {\n                do {\n                    let cacheBookmark = try cacheDirectory.bookmarkData(\n                        options: .withSecurityScope,\n                        includingResourceValuesForKeys: nil,\n                        relativeTo: nil)\n                    PrefsCache.supportBookmarkData = cacheBookmark\n\n                } catch let error {\n                    debugLog(\"Error saving the security scoped bookmark \\(error)\")\n                }\n            }\n\n            Aerial.helper.showInfoAlert(title: \"Cache path changed\",\n                                 text: \"In order for your new cache path to take effect, please close this panel and System Preferences.\")\n        }\n    }\n\n    @IBAction func makeTimeMachineIgnore(_ sender: NSButton) {\n        if sender.state == .on {\n            TimeMachine.exclude()\n        } else {\n            TimeMachine.reinclude()\n        }\n    }\n\n    @IBAction func manuallyPIckClick(_ sender: NSButton) {\n        PrefsCache.overrideCache = sender.state == .on\n        updateCachePath()\n    }\n}\n"
  },
  {
    "path": "Resources/MainUI/Settings panels/CacheViewController.xib",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.Cocoa.XIB\" version=\"3.0\" toolsVersion=\"21701\" targetRuntime=\"MacOSX.Cocoa\" propertyAccessControl=\"none\" useAutolayout=\"YES\" customObjectInstantitationMethod=\"direct\">\n    <dependencies>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.CocoaPlugin\" version=\"21701\"/>\n        <capability name=\"Image references\" minToolsVersion=\"12.0\"/>\n        <capability name=\"System colors introduced in macOS 10.14\" minToolsVersion=\"10.0\"/>\n        <capability name=\"documents saved in the Xcode 8 format\" minToolsVersion=\"8.0\"/>\n    </dependencies>\n    <objects>\n        <customObject id=\"-2\" userLabel=\"File's Owner\" customClass=\"CacheViewController\" customModule=\"Aerial\" customModuleProvider=\"target\">\n            <connections>\n                <outlet property=\"addCurrentNetworkButton\" destination=\"Kpn-Oc-zFD\" id=\"2R7-hQ-QAH\"/>\n                <outlet property=\"allowedListLabel\" destination=\"l6E-tF-sRt\" id=\"mF2-b1-Dw1\"/>\n                <outlet property=\"automaticContainerView\" destination=\"u4o-WA-mfN\" id=\"1uo-Sh-XBL\"/>\n                <outlet property=\"automaticallyDownloadCheckbox\" destination=\"hc3-Qt-NLz\" id=\"bS2-FA-qS6\"/>\n                <outlet property=\"cacheBox\" destination=\"uMh-u9-z5G\" id=\"MmT-ih-Qbu\"/>\n                <outlet property=\"cacheSize\" destination=\"WTL-hI-TCP\" id=\"FDj-8B-gR6\"/>\n                <outlet property=\"connectedIcon\" destination=\"mFt-fb-1OS\" id=\"CIJ-6I-NJc\"/>\n                <outlet property=\"connectedLabel\" destination=\"agU-a4-AzS\" id=\"yJB-oH-kVN\"/>\n                <outlet property=\"freeBox\" destination=\"Asz-AC-wek\" id=\"1mf-QA-xwu\"/>\n                <outlet property=\"limitLabel\" destination=\"uaY-f5-FSu\" id=\"aEP-sp-Uqp\"/>\n                <outlet property=\"limitSlider\" destination=\"RaB-PR-zBP\" id=\"wyD-Js-M1W\"/>\n                <outlet property=\"limitTextField\" destination=\"1wh-wp-MNi\" id=\"dMW-Vn-e2G\"/>\n                <outlet property=\"limitUnitLabel\" destination=\"IrX-JD-reU\" id=\"Iyo-jr-03k\"/>\n                <outlet property=\"makeTimeMachineIgnore\" destination=\"mGa-dk-kQF\" id=\"IVk-iq-OTk\"/>\n                <outlet property=\"makeTimeMachineIgnore2\" destination=\"NL5-7q-3LX\" id=\"YJh-Gf-H4V\"/>\n                <outlet property=\"manualContainerView\" destination=\"Epz-1h-oTj\" id=\"m7f-t9-aRW\"/>\n                <outlet property=\"manuallyPick\" destination=\"nDP-xy-8Ig\" id=\"Bkt-BF-Ija\"/>\n                <outlet property=\"manuallyPickLabel\" destination=\"nB4-bN-Nk2\" id=\"PYK-wq-kOF\"/>\n                <outlet property=\"packsBox\" destination=\"PFq-go-H6W\" id=\"Yne-KY-uzL\"/>\n                <outlet property=\"pickFolder\" destination=\"opJ-yV-dsw\" id=\"i3c-11-o20\"/>\n                <outlet property=\"resetListButton\" destination=\"frC-4B-UNN\" id=\"ggc-G3-rJZ\"/>\n                <outlet property=\"restrictWiFiCheckbox\" destination=\"eO9-gC-aqe\" id=\"atJ-yQ-S9U\"/>\n                <outlet property=\"rotateFrequencyLabel\" destination=\"hTY-9R-NMo\" id=\"uep-h0-RBE\"/>\n                <outlet property=\"rotateFrequencyPopup\" destination=\"Fx0-Ue-MbY\" id=\"s1o-IX-lWh\"/>\n                <outlet property=\"showDownloadIndicator\" destination=\"HHE-WL-n3w\" id=\"yE4-GY-Zlj\"/>\n                <outlet property=\"view\" destination=\"Hz6-mo-xeY\" id=\"0bl-1N-x8E\"/>\n            </connections>\n        </customObject>\n        <customObject id=\"-1\" userLabel=\"First Responder\" customClass=\"FirstResponder\"/>\n        <customObject id=\"-3\" userLabel=\"Application\" customClass=\"NSObject\"/>\n        <customView translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Hz6-mo-xeY\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"811\" height=\"830\"/>\n            <subviews>\n                <customView translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"u4o-WA-mfN\">\n                    <rect key=\"frame\" x=\"16\" y=\"284\" width=\"779\" height=\"300\"/>\n                    <subviews>\n                        <textField verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"1wh-wp-MNi\">\n                            <rect key=\"frame\" x=\"423\" y=\"277\" width=\"33\" height=\"22\"/>\n                            <constraints>\n                                <constraint firstAttribute=\"width\" constant=\"33\" id=\"VId-kn-hXK\"/>\n                            </constraints>\n                            <textFieldCell key=\"cell\" controlSize=\"large\" scrollable=\"YES\" lineBreakMode=\"clipping\" selectable=\"YES\" editable=\"YES\" sendsActionOnEndEditing=\"YES\" state=\"on\" borderStyle=\"bezel\" alignment=\"right\" title=\"5\" drawsBackground=\"YES\" id=\"LUn-uA-g7s\">\n                                <numberFormatter key=\"formatter\" formatterBehavior=\"default10_4\" numberStyle=\"decimal\" formatWidth=\"-1\" minimumIntegerDigits=\"1\" maximumIntegerDigits=\"2000000000\" maximumFractionDigits=\"3\" id=\"aGc-v8-HIq\">\n                                    <real key=\"minimum\" value=\"1\"/>\n                                    <real key=\"maximum\" value=\"60\"/>\n                                </numberFormatter>\n                                <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                            </textFieldCell>\n                            <connections>\n                                <action selector=\"limitTextFieldChange:\" target=\"-2\" id=\"Npl-Z9-PIY\"/>\n                            </connections>\n                        </textField>\n                        <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"IrX-JD-reU\">\n                            <rect key=\"frame\" x=\"462\" y=\"279\" width=\"24\" height=\"17\"/>\n                            <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" title=\"GB\" id=\"z4c-yB-k4e\">\n                                <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                            </textFieldCell>\n                        </textField>\n                        <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"cW8-Ta-PzR\">\n                            <rect key=\"frame\" x=\"49\" y=\"279\" width=\"129\" height=\"17\"/>\n                            <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" alignment=\"right\" title=\"Limit cache size to:\" id=\"DLv-dB-sq0\">\n                                <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                            </textFieldCell>\n                        </textField>\n                        <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"eO9-gC-aqe\">\n                            <rect key=\"frame\" x=\"181\" y=\"128.5\" width=\"321\" height=\"22\"/>\n                            <buttonCell key=\"cell\" type=\"check\" title=\"Restrict downloads to trusted Wi-Fi networks\" bezelStyle=\"regularSquare\" imagePosition=\"left\" controlSize=\"large\" state=\"on\" inset=\"2\" id=\"7lW-xd-wEA\">\n                                <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                                <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                            </buttonCell>\n                            <connections>\n                                <action selector=\"restrictWiFiCheck:\" target=\"-2\" id=\"Jpp-05-2KL\"/>\n                            </connections>\n                        </button>\n                        <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Kpn-Oc-zFD\">\n                            <rect key=\"frame\" x=\"178\" y=\"49\" width=\"165\" height=\"40\"/>\n                            <buttonCell key=\"cell\" type=\"push\" title=\"Add current network\" bezelStyle=\"rounded\" alignment=\"center\" controlSize=\"large\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"jY1-rg-JFf\">\n                                <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                                <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                            </buttonCell>\n                            <connections>\n                                <action selector=\"addCurrentNetworkClick:\" target=\"-2\" id=\"93G-1M-BPb\"/>\n                            </connections>\n                        </button>\n                        <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"l6E-tF-sRt\">\n                            <rect key=\"frame\" x=\"182\" y=\"22\" width=\"63\" height=\"17\"/>\n                            <textFieldCell key=\"cell\" controlSize=\"large\" title=\"Allowed: \" id=\"HwM-ON-Dvy\">\n                                <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                            </textFieldCell>\n                        </textField>\n                        <button translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"mFt-fb-1OS\">\n                            <rect key=\"frame\" x=\"184\" y=\"99\" width=\"16\" height=\"16\"/>\n                            <buttonCell key=\"cell\" type=\"square\" bezelStyle=\"shadowlessSquare\" image=\"NSStatusAvailable\" imagePosition=\"only\" alignment=\"center\" controlSize=\"large\" imageScaling=\"proportionallyUpOrDown\" inset=\"2\" id=\"hz1-x9-iK0\">\n                                <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                                <font key=\"font\" metaFont=\"system\"/>\n                            </buttonCell>\n                        </button>\n                        <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"agU-a4-AzS\">\n                            <rect key=\"frame\" x=\"203\" y=\"98\" width=\"100\" height=\"17\"/>\n                            <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" title=\"Connected to: \" id=\"GbJ-ZN-k25\">\n                                <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                            </textFieldCell>\n                        </textField>\n                        <slider verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"RaB-PR-zBP\">\n                            <rect key=\"frame\" x=\"182\" y=\"270\" width=\"221\" height=\"28\"/>\n                            <constraints>\n                                <constraint firstAttribute=\"width\" constant=\"217\" id=\"ipz-RT-lRq\"/>\n                            </constraints>\n                            <sliderCell key=\"cell\" controlSize=\"large\" state=\"on\" alignment=\"left\" minValue=\"1\" maxValue=\"101\" doubleValue=\"5\" tickMarkPosition=\"below\" numberOfTickMarks=\"9\" sliderType=\"linear\" id=\"BVi-87-dJN\"/>\n                            <connections>\n                                <action selector=\"limitSliderChange:\" target=\"-2\" id=\"i84-Z3-DXI\"/>\n                            </connections>\n                        </slider>\n                        <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"I6n-yR-diw\">\n                            <rect key=\"frame\" x=\"184\" y=\"258\" width=\"28\" height=\"14\"/>\n                            <textFieldCell key=\"cell\" controlSize=\"small\" lineBreakMode=\"clipping\" title=\"1 GB\" id=\"o3E-dq-K0M\">\n                                <font key=\"font\" metaFont=\"smallSystem\"/>\n                                <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                            </textFieldCell>\n                        </textField>\n                        <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"YDt-7V-EeW\">\n                            <rect key=\"frame\" x=\"375\" y=\"260\" width=\"58\" height=\"14\"/>\n                            <textFieldCell key=\"cell\" controlSize=\"small\" lineBreakMode=\"clipping\" alignment=\"center\" title=\"Unlimited\" id=\"OjV-g1-U8U\">\n                                <font key=\"font\" metaFont=\"smallSystem\"/>\n                                <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                            </textFieldCell>\n                        </textField>\n                        <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"hTY-9R-NMo\">\n                            <rect key=\"frame\" x=\"72\" y=\"221\" width=\"106\" height=\"17\"/>\n                            <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" alignment=\"right\" title=\"Replace videos:\" id=\"HcU-b8-0LK\">\n                                <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                            </textFieldCell>\n                        </textField>\n                        <popUpButton verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Fx0-Ue-MbY\">\n                            <rect key=\"frame\" x=\"179\" y=\"208\" width=\"101\" height=\"40\"/>\n                            <popUpButtonCell key=\"cell\" type=\"push\" title=\"Daily\" bezelStyle=\"rounded\" alignment=\"left\" controlSize=\"large\" lineBreakMode=\"truncatingTail\" state=\"on\" borderStyle=\"borderAndBezel\" imageScaling=\"proportionallyDown\" inset=\"2\" selectedItem=\"PG0-fw-tgh\" id=\"EuB-mx-EcZ\">\n                                <behavior key=\"behavior\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                                <font key=\"font\" size=\"14\" name=\"HelveticaNeue\"/>\n                                <menu key=\"menu\" id=\"pKZ-La-65o\">\n                                    <items>\n                                        <menuItem title=\"Daily\" state=\"on\" id=\"PG0-fw-tgh\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                        </menuItem>\n                                        <menuItem title=\"Weekly\" id=\"2oT-7A-P9y\"/>\n                                        <menuItem title=\"Monthly\" id=\"xUG-FE-YKk\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                        </menuItem>\n                                        <menuItem title=\"Never\" id=\"rjd-3p-89y\"/>\n                                    </items>\n                                </menu>\n                            </popUpButtonCell>\n                            <connections>\n                                <action selector=\"rotateFrequencyChange:\" target=\"-2\" id=\"ppr-pX-1aR\"/>\n                            </connections>\n                        </popUpButton>\n                        <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"frC-4B-UNN\">\n                            <rect key=\"frame\" x=\"343\" y=\"49\" width=\"92\" height=\"40\"/>\n                            <buttonCell key=\"cell\" type=\"push\" title=\"Reset list\" bezelStyle=\"rounded\" alignment=\"center\" controlSize=\"large\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"JAx-l1-U4r\">\n                                <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                                <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                            </buttonCell>\n                            <connections>\n                                <action selector=\"resetListClick:\" target=\"-2\" id=\"7sH-5V-n1R\"/>\n                            </connections>\n                        </button>\n                        <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"HHE-WL-n3w\">\n                            <rect key=\"frame\" x=\"181\" y=\"178.5\" width=\"317\" height=\"22\"/>\n                            <buttonCell key=\"cell\" type=\"check\" title=\"Show download progress in the screen saver\" bezelStyle=\"regularSquare\" imagePosition=\"left\" controlSize=\"large\" inset=\"2\" id=\"EcB-oi-vVw\">\n                                <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                                <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                            </buttonCell>\n                            <connections>\n                                <action selector=\"showDownloadIndicatorChange:\" target=\"-2\" id=\"e6b-oJ-MSH\"/>\n                            </connections>\n                        </button>\n                        <box verticalHuggingPriority=\"750\" boxType=\"separator\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"qCm-Xg-sGD\">\n                            <rect key=\"frame\" x=\"8\" y=\"162\" width=\"763\" height=\"5\"/>\n                        </box>\n                        <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Yd1-B2-AiX\">\n                            <rect key=\"frame\" x=\"281\" y=\"221\" width=\"436\" height=\"17\"/>\n                            <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"(if your cache is full, older videos will be replaced with newer ones)\" id=\"xbm-Ev-ZSe\">\n                                <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                            </textFieldCell>\n                        </textField>\n                    </subviews>\n                    <constraints>\n                        <constraint firstItem=\"eO9-gC-aqe\" firstAttribute=\"top\" secondItem=\"qCm-Xg-sGD\" secondAttribute=\"bottom\" constant=\"16\" id=\"0a1-QJ-ePE\"/>\n                        <constraint firstItem=\"l6E-tF-sRt\" firstAttribute=\"top\" secondItem=\"Kpn-Oc-zFD\" secondAttribute=\"bottom\" constant=\"16\" id=\"7mI-Fp-Ehv\"/>\n                        <constraint firstAttribute=\"height\" constant=\"300\" id=\"8LB-lh-D2X\"/>\n                        <constraint firstItem=\"Yd1-B2-AiX\" firstAttribute=\"firstBaseline\" secondItem=\"hTY-9R-NMo\" secondAttribute=\"firstBaseline\" id=\"B8v-IJ-b7j\"/>\n                        <constraint firstItem=\"agU-a4-AzS\" firstAttribute=\"centerY\" secondItem=\"mFt-fb-1OS\" secondAttribute=\"centerY\" id=\"DUN-cO-SgN\"/>\n                        <constraint firstItem=\"mFt-fb-1OS\" firstAttribute=\"leading\" secondItem=\"u4o-WA-mfN\" secondAttribute=\"leading\" constant=\"184\" id=\"EhH-wn-maW\"/>\n                        <constraint firstItem=\"RaB-PR-zBP\" firstAttribute=\"firstBaseline\" secondItem=\"cW8-Ta-PzR\" secondAttribute=\"firstBaseline\" id=\"HCz-C4-6xe\"/>\n                        <constraint firstItem=\"Kpn-Oc-zFD\" firstAttribute=\"leading\" secondItem=\"u4o-WA-mfN\" secondAttribute=\"leading\" constant=\"184\" id=\"ITi-3t-Wyo\"/>\n                        <constraint firstItem=\"I6n-yR-diw\" firstAttribute=\"leading\" secondItem=\"u4o-WA-mfN\" secondAttribute=\"leading\" constant=\"186\" id=\"JDP-2Q-dS7\"/>\n                        <constraint firstItem=\"Fx0-Ue-MbY\" firstAttribute=\"leading\" secondItem=\"u4o-WA-mfN\" secondAttribute=\"leading\" constant=\"184\" id=\"KsA-nF-ABl\"/>\n                        <constraint firstItem=\"Yd1-B2-AiX\" firstAttribute=\"leading\" secondItem=\"Fx0-Ue-MbY\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"LSd-cu-PGW\"/>\n                        <constraint firstItem=\"I6n-yR-diw\" firstAttribute=\"top\" secondItem=\"RaB-PR-zBP\" secondAttribute=\"bottom\" constant=\"4\" id=\"Ly4-jO-EuQ\"/>\n                        <constraint firstItem=\"RaB-PR-zBP\" firstAttribute=\"leading\" secondItem=\"cW8-Ta-PzR\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"M6b-dj-mqb\"/>\n                        <constraint firstItem=\"YDt-7V-EeW\" firstAttribute=\"top\" secondItem=\"1wh-wp-MNi\" secondAttribute=\"bottom\" constant=\"3\" id=\"N1c-wD-lIE\"/>\n                        <constraint firstItem=\"IrX-JD-reU\" firstAttribute=\"leading\" secondItem=\"1wh-wp-MNi\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"NMb-p5-wBr\"/>\n                        <constraint firstItem=\"l6E-tF-sRt\" firstAttribute=\"leading\" secondItem=\"u4o-WA-mfN\" secondAttribute=\"leading\" constant=\"184\" id=\"Ne9-pb-LCT\"/>\n                        <constraint firstItem=\"frC-4B-UNN\" firstAttribute=\"firstBaseline\" secondItem=\"Kpn-Oc-zFD\" secondAttribute=\"firstBaseline\" id=\"Omu-MG-Txm\"/>\n                        <constraint firstAttribute=\"trailing\" secondItem=\"qCm-Xg-sGD\" secondAttribute=\"trailing\" constant=\"8\" id=\"Or3-zB-Eb0\"/>\n                        <constraint firstItem=\"1wh-wp-MNi\" firstAttribute=\"leading\" secondItem=\"RaB-PR-zBP\" secondAttribute=\"trailing\" constant=\"22\" id=\"RbY-2L-g3G\"/>\n                        <constraint firstItem=\"agU-a4-AzS\" firstAttribute=\"leading\" secondItem=\"mFt-fb-1OS\" secondAttribute=\"trailing\" constant=\"5\" id=\"VFg-8t-Pb3\"/>\n                        <constraint firstItem=\"Fx0-Ue-MbY\" firstAttribute=\"firstBaseline\" secondItem=\"hTY-9R-NMo\" secondAttribute=\"firstBaseline\" id=\"WTl-Ze-cN1\"/>\n                        <constraint firstItem=\"qCm-Xg-sGD\" firstAttribute=\"top\" secondItem=\"HHE-WL-n3w\" secondAttribute=\"bottom\" constant=\"16\" id=\"Wz3-a2-HzE\"/>\n                        <constraint firstItem=\"frC-4B-UNN\" firstAttribute=\"leading\" secondItem=\"Kpn-Oc-zFD\" secondAttribute=\"trailing\" constant=\"12\" symbolic=\"YES\" id=\"abx-eM-MBu\"/>\n                        <constraint firstItem=\"RaB-PR-zBP\" firstAttribute=\"leading\" secondItem=\"u4o-WA-mfN\" secondAttribute=\"leading\" constant=\"184\" id=\"dfy-XE-CeH\"/>\n                        <constraint firstItem=\"HHE-WL-n3w\" firstAttribute=\"leading\" secondItem=\"Fx0-Ue-MbY\" secondAttribute=\"leading\" id=\"dzN-Xd-hLN\"/>\n                        <constraint firstItem=\"qCm-Xg-sGD\" firstAttribute=\"leading\" secondItem=\"u4o-WA-mfN\" secondAttribute=\"leading\" constant=\"8\" id=\"eAq-P6-U2o\"/>\n                        <constraint firstItem=\"Fx0-Ue-MbY\" firstAttribute=\"top\" secondItem=\"I6n-yR-diw\" secondAttribute=\"bottom\" constant=\"16\" id=\"nsb-h8-1Bz\"/>\n                        <constraint firstItem=\"Fx0-Ue-MbY\" firstAttribute=\"leading\" secondItem=\"hTY-9R-NMo\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"oaw-RX-zje\"/>\n                        <constraint firstItem=\"RaB-PR-zBP\" firstAttribute=\"top\" secondItem=\"u4o-WA-mfN\" secondAttribute=\"top\" constant=\"4\" id=\"ofl-kK-NVN\"/>\n                        <constraint firstItem=\"Kpn-Oc-zFD\" firstAttribute=\"top\" secondItem=\"mFt-fb-1OS\" secondAttribute=\"bottom\" constant=\"16\" id=\"ow4-Vd-Ysz\"/>\n                        <constraint firstItem=\"HHE-WL-n3w\" firstAttribute=\"top\" secondItem=\"Fx0-Ue-MbY\" secondAttribute=\"bottom\" constant=\"16\" id=\"pbO-nT-YvP\"/>\n                        <constraint firstItem=\"eO9-gC-aqe\" firstAttribute=\"leading\" secondItem=\"u4o-WA-mfN\" secondAttribute=\"leading\" constant=\"184\" id=\"qLH-I6-SYA\"/>\n                        <constraint firstItem=\"1wh-wp-MNi\" firstAttribute=\"firstBaseline\" secondItem=\"cW8-Ta-PzR\" secondAttribute=\"firstBaseline\" id=\"rxk-jB-yi3\"/>\n                        <constraint firstItem=\"IrX-JD-reU\" firstAttribute=\"firstBaseline\" secondItem=\"cW8-Ta-PzR\" secondAttribute=\"firstBaseline\" id=\"s3g-7f-U2a\"/>\n                        <constraint firstItem=\"YDt-7V-EeW\" firstAttribute=\"leading\" secondItem=\"I6n-yR-diw\" secondAttribute=\"trailing\" constant=\"167\" id=\"wiM-sM-THR\"/>\n                        <constraint firstItem=\"agU-a4-AzS\" firstAttribute=\"top\" secondItem=\"eO9-gC-aqe\" secondAttribute=\"bottom\" constant=\"16\" id=\"wiR-8z-ajm\"/>\n                    </constraints>\n                </customView>\n                <customView translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"g6L-Vy-rKN\">\n                    <rect key=\"frame\" x=\"16\" y=\"722\" width=\"779\" height=\"54\"/>\n                    <subviews>\n                        <box fixedFrame=\"YES\" boxType=\"custom\" title=\"Box\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"uMh-u9-z5G\">\n                            <rect key=\"frame\" x=\"184\" y=\"29\" width=\"153\" height=\"25\"/>\n                            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                            <view key=\"contentView\" id=\"cVa-UH-ybi\">\n                                <rect key=\"frame\" x=\"1\" y=\"1\" width=\"151\" height=\"23\"/>\n                                <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                                <subviews>\n                                    <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"G9x-bl-vJK\">\n                                        <rect key=\"frame\" x=\"56\" y=\"4\" width=\"40\" height=\"15\"/>\n                                        <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"Cache\" id=\"coI-xi-DVR\">\n                                            <font key=\"font\" metaFont=\"cellTitle\"/>\n                                            <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                            <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                        </textFieldCell>\n                                    </textField>\n                                </subviews>\n                                <constraints>\n                                    <constraint firstItem=\"G9x-bl-vJK\" firstAttribute=\"centerY\" secondItem=\"cVa-UH-ybi\" secondAttribute=\"centerY\" id=\"aJE-47-uai\"/>\n                                    <constraint firstItem=\"G9x-bl-vJK\" firstAttribute=\"centerX\" secondItem=\"cVa-UH-ybi\" secondAttribute=\"centerX\" id=\"dg3-TT-evg\"/>\n                                </constraints>\n                            </view>\n                            <color key=\"fillColor\" name=\"systemIndigoColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        </box>\n                        <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"uaY-f5-FSu\">\n                            <rect key=\"frame\" x=\"67\" y=\"8\" width=\"646\" height=\"16\"/>\n                            <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" title=\"Total usage 40 GB (8 GB for packs, 32 GB for the cache, still 8 GB of free cache available for more videos)\" id=\"VPN-wd-3Px\">\n                                <font key=\"font\" metaFont=\"system\"/>\n                                <color key=\"textColor\" name=\"secondaryLabelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                            </textFieldCell>\n                        </textField>\n                        <box toolTip=\"Video packs are made by third party and are downloaded once, they are not part of Aerial's cache\" fixedFrame=\"YES\" boxType=\"custom\" title=\"Box\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"PFq-go-H6W\">\n                            <rect key=\"frame\" x=\"346\" y=\"29\" width=\"80\" height=\"25\"/>\n                            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                            <view key=\"contentView\" id=\"CpA-MN-6iK\">\n                                <rect key=\"frame\" x=\"1\" y=\"1\" width=\"78\" height=\"23\"/>\n                                <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                                <subviews>\n                                    <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"gqg-D4-Gcg\">\n                                        <rect key=\"frame\" x=\"20\" y=\"4\" width=\"38\" height=\"15\"/>\n                                        <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"Packs\" id=\"MbW-vO-gcQ\">\n                                            <font key=\"font\" metaFont=\"cellTitle\"/>\n                                            <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                            <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                        </textFieldCell>\n                                    </textField>\n                                </subviews>\n                                <constraints>\n                                    <constraint firstItem=\"gqg-D4-Gcg\" firstAttribute=\"centerY\" secondItem=\"CpA-MN-6iK\" secondAttribute=\"centerY\" id=\"Pbx-DK-t9W\"/>\n                                    <constraint firstItem=\"gqg-D4-Gcg\" firstAttribute=\"centerX\" secondItem=\"CpA-MN-6iK\" secondAttribute=\"centerX\" id=\"ofp-RR-WxW\"/>\n                                </constraints>\n                            </view>\n                            <color key=\"fillColor\" name=\"systemMintColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        </box>\n                        <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"YWN-Hr-d3G\">\n                            <rect key=\"frame\" x=\"99\" y=\"34\" width=\"79\" height=\"17\"/>\n                            <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" alignment=\"right\" title=\"Disk usage:\" id=\"Fus-gy-WLi\">\n                                <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                            </textFieldCell>\n                        </textField>\n                        <box fixedFrame=\"YES\" boxType=\"custom\" title=\"Free\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Asz-AC-wek\">\n                            <rect key=\"frame\" x=\"446\" y=\"29\" width=\"144\" height=\"25\"/>\n                            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                            <view key=\"contentView\" id=\"ov2-1h-Mui\">\n                                <rect key=\"frame\" x=\"1\" y=\"1\" width=\"142\" height=\"23\"/>\n                                <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                                <subviews>\n                                    <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"96i-aD-JIX\">\n                                        <rect key=\"frame\" x=\"57\" y=\"4\" width=\"29\" height=\"15\"/>\n                                        <textFieldCell key=\"cell\" scrollable=\"YES\" lineBreakMode=\"clipping\" title=\"Free\" id=\"HV6-vP-hq6\">\n                                            <font key=\"font\" metaFont=\"cellTitle\"/>\n                                            <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                            <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                        </textFieldCell>\n                                    </textField>\n                                </subviews>\n                                <constraints>\n                                    <constraint firstItem=\"96i-aD-JIX\" firstAttribute=\"centerY\" secondItem=\"ov2-1h-Mui\" secondAttribute=\"centerY\" id=\"CJo-VX-RPO\"/>\n                                    <constraint firstItem=\"96i-aD-JIX\" firstAttribute=\"centerX\" secondItem=\"ov2-1h-Mui\" secondAttribute=\"centerX\" id=\"Zwj-lS-T7x\"/>\n                                </constraints>\n                            </view>\n                            <color key=\"fillColor\" name=\"systemGrayColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        </box>\n                    </subviews>\n                    <constraints>\n                        <constraint firstItem=\"uaY-f5-FSu\" firstAttribute=\"centerX\" secondItem=\"g6L-Vy-rKN\" secondAttribute=\"centerX\" id=\"0vB-3H-dFg\"/>\n                        <constraint firstItem=\"YWN-Hr-d3G\" firstAttribute=\"top\" secondItem=\"g6L-Vy-rKN\" secondAttribute=\"top\" constant=\"3\" id=\"cS8-ge-RNn\"/>\n                        <constraint firstItem=\"uaY-f5-FSu\" firstAttribute=\"top\" secondItem=\"g6L-Vy-rKN\" secondAttribute=\"top\" constant=\"30\" id=\"lT6-zo-Q9l\"/>\n                        <constraint firstAttribute=\"height\" constant=\"54\" id=\"sO0-CM-8n3\"/>\n                        <constraint firstItem=\"YWN-Hr-d3G\" firstAttribute=\"leading\" secondItem=\"g6L-Vy-rKN\" secondAttribute=\"leading\" constant=\"101\" id=\"tIY-9n-IWd\"/>\n                    </constraints>\n                </customView>\n                <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"mGa-dk-kQF\">\n                    <rect key=\"frame\" x=\"197\" y=\"630.5\" width=\"270\" height=\"22\"/>\n                    <buttonCell key=\"cell\" type=\"check\" title=\"Make Time Machine ignore the cache\" bezelStyle=\"regularSquare\" imagePosition=\"left\" controlSize=\"large\" inset=\"2\" id=\"Ks6-Om-6My\">\n                        <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"makeTimeMachineIgnore:\" target=\"-2\" id=\"bD8-2R-m2P\"/>\n                    </connections>\n                </button>\n                <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"nDP-xy-8Ig\">\n                    <rect key=\"frame\" x=\"197\" y=\"686.5\" width=\"215\" height=\"22\"/>\n                    <buttonCell key=\"cell\" type=\"check\" title=\"Manually pick cache location\" bezelStyle=\"regularSquare\" imagePosition=\"left\" controlSize=\"large\" inset=\"2\" id=\"93S-2c-Vpk\">\n                        <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"manuallyPIckClick:\" target=\"-2\" id=\"6Px-mU-1A1\"/>\n                    </connections>\n                </button>\n                <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"nB4-bN-Nk2\">\n                    <rect key=\"frame\" x=\"220\" y=\"662\" width=\"444\" height=\"15\"/>\n                    <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"Because of security restrictions, this option requires macOS Monterey or later\" id=\"DKN-y4-Ctc\">\n                        <font key=\"font\" metaFont=\"cellTitle\"/>\n                        <color key=\"textColor\" name=\"secondaryLabelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"opJ-yV-dsw\">\n                    <rect key=\"frame\" x=\"613\" y=\"676\" width=\"125\" height=\"40\"/>\n                    <buttonCell key=\"cell\" type=\"push\" title=\"Pick Folder\" bezelStyle=\"rounded\" image=\"folder.badge.gearshape\" catalog=\"system\" imagePosition=\"left\" alignment=\"center\" controlSize=\"large\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"61J-7N-dOP\">\n                        <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"pickFolderButton:\" target=\"-2\" id=\"gPv-l4-nTp\"/>\n                    </connections>\n                </button>\n                <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"hBb-m4-Lg5\">\n                    <rect key=\"frame\" x=\"52\" y=\"797\" width=\"363\" height=\"17\"/>\n                    <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"Change cache location and how videos are downloaded\" id=\"E6y-lf-REM\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <imageView horizontalHuggingPriority=\"25\" verticalHuggingPriority=\"25\" horizontalCompressionResistancePriority=\"75\" verticalCompressionResistancePriority=\"75\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"dxs-EH-Lk0\">\n                    <rect key=\"frame\" x=\"16\" y=\"782\" width=\"28.5\" height=\"42\"/>\n                    <constraints>\n                        <constraint firstAttribute=\"height\" constant=\"34\" id=\"3Lu-OB-rTe\"/>\n                        <constraint firstAttribute=\"width\" constant=\"28\" id=\"SYm-kY-92v\"/>\n                    </constraints>\n                    <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyUpOrDown\" id=\"0io-kM-iGx\">\n                        <imageReference key=\"image\" image=\"internaldrive\" catalog=\"system\" symbolScale=\"large\"/>\n                    </imageCell>\n                    <color key=\"contentTintColor\" name=\"controlAccentColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                </imageView>\n                <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"UgL-8O-Ljc\">\n                    <rect key=\"frame\" x=\"465\" y=\"676\" width=\"148\" height=\"40\"/>\n                    <buttonCell key=\"cell\" type=\"push\" title=\"Show in Finder\" bezelStyle=\"rounded\" image=\"folder\" catalog=\"system\" imagePosition=\"left\" alignment=\"center\" controlSize=\"large\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"NJy-ug-gBa\">\n                        <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"showInFinderClick:\" target=\"-2\" id=\"urq-YZ-gyd\"/>\n                    </connections>\n                </button>\n                <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"hc3-Qt-NLz\">\n                    <rect key=\"frame\" x=\"197\" y=\"597.5\" width=\"229\" height=\"22\"/>\n                    <buttonCell key=\"cell\" type=\"check\" title=\"Automatically download videos\" bezelStyle=\"regularSquare\" imagePosition=\"left\" controlSize=\"large\" state=\"on\" inset=\"2\" id=\"5FO-fZ-i1A\">\n                        <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"automaticallyDownloadClick:\" target=\"-2\" id=\"EaX-rA-Q8z\"/>\n                    </connections>\n                </button>\n                <customView translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Epz-1h-oTj\">\n                    <rect key=\"frame\" x=\"16\" y=\"458\" width=\"779\" height=\"126\"/>\n                    <subviews>\n                        <textField verticalHuggingPriority=\"750\" horizontalCompressionResistancePriority=\"250\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"k6x-vV-geU\">\n                            <rect key=\"frame\" x=\"182\" y=\"101\" width=\"454\" height=\"17\"/>\n                            <textFieldCell key=\"cell\" selectable=\"YES\" title=\"You can manually download or manage your cache from the video list.\" id=\"XE8-MB-KvC\">\n                                <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                            </textFieldCell>\n                        </textField>\n                        <button translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Pzb-yH-L4O\">\n                            <rect key=\"frame\" x=\"154\" y=\"99\" width=\"22\" height=\"22\"/>\n                            <constraints>\n                                <constraint firstAttribute=\"height\" constant=\"22\" id=\"1zm-5q-hAh\"/>\n                                <constraint firstAttribute=\"width\" constant=\"22\" id=\"CVq-hN-mLU\"/>\n                            </constraints>\n                            <buttonCell key=\"cell\" type=\"square\" bezelStyle=\"shadowlessSquare\" image=\"NSInfo\" imagePosition=\"only\" alignment=\"center\" imageScaling=\"proportionallyUpOrDown\" inset=\"2\" id=\"I5o-hM-yIi\">\n                                <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                                <font key=\"font\" metaFont=\"system\"/>\n                            </buttonCell>\n                        </button>\n                        <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"WTL-hI-TCP\">\n                            <rect key=\"frame\" x=\"182\" y=\"66\" width=\"137\" height=\"17\"/>\n                            <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"Current cache size : \" id=\"LuH-hC-uzW\">\n                                <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                            </textFieldCell>\n                        </textField>\n                        <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"NL5-7q-3LX\">\n                            <rect key=\"frame\" x=\"181\" y=\"30.5\" width=\"270\" height=\"22\"/>\n                            <buttonCell key=\"cell\" type=\"check\" title=\"Make Time Machine ignore the cache\" bezelStyle=\"regularSquare\" imagePosition=\"left\" controlSize=\"large\" inset=\"2\" id=\"E2h-9k-N6w\">\n                                <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                                <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                            </buttonCell>\n                            <connections>\n                                <action selector=\"makeTimeMachineIgnore:\" target=\"-2\" id=\"msy-vK-w42\"/>\n                            </connections>\n                        </button>\n                    </subviews>\n                    <constraints>\n                        <constraint firstItem=\"k6x-vV-geU\" firstAttribute=\"leading\" secondItem=\"Epz-1h-oTj\" secondAttribute=\"leading\" constant=\"184\" id=\"5ys-mA-npB\"/>\n                        <constraint firstItem=\"NL5-7q-3LX\" firstAttribute=\"top\" secondItem=\"WTL-hI-TCP\" secondAttribute=\"bottom\" constant=\"16\" id=\"8Pi-9x-SxP\"/>\n                        <constraint firstItem=\"Pzb-yH-L4O\" firstAttribute=\"top\" secondItem=\"Epz-1h-oTj\" secondAttribute=\"top\" constant=\"5\" id=\"9a8-eP-1wm\"/>\n                        <constraint firstItem=\"NL5-7q-3LX\" firstAttribute=\"leading\" secondItem=\"WTL-hI-TCP\" secondAttribute=\"leading\" id=\"Cq8-Hq-rNi\"/>\n                        <constraint firstItem=\"k6x-vV-geU\" firstAttribute=\"leading\" secondItem=\"Pzb-yH-L4O\" secondAttribute=\"trailing\" constant=\"8\" id=\"RUF-2x-UYq\"/>\n                        <constraint firstItem=\"WTL-hI-TCP\" firstAttribute=\"leading\" secondItem=\"Epz-1h-oTj\" secondAttribute=\"leading\" constant=\"184\" id=\"TIo-2b-zKg\"/>\n                        <constraint firstAttribute=\"height\" constant=\"126\" id=\"YaW-fN-uL7\"/>\n                        <constraint firstItem=\"WTL-hI-TCP\" firstAttribute=\"top\" secondItem=\"Pzb-yH-L4O\" secondAttribute=\"bottom\" constant=\"16\" id=\"jE5-g0-9oO\"/>\n                        <constraint firstItem=\"k6x-vV-geU\" firstAttribute=\"top\" secondItem=\"Epz-1h-oTj\" secondAttribute=\"top\" constant=\"8\" id=\"vag-fm-3JR\"/>\n                    </constraints>\n                </customView>\n            </subviews>\n            <constraints>\n                <constraint firstItem=\"hc3-Qt-NLz\" firstAttribute=\"leading\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"leading\" constant=\"200\" id=\"1i4-dM-dRw\"/>\n                <constraint firstItem=\"hc3-Qt-NLz\" firstAttribute=\"leading\" secondItem=\"nDP-xy-8Ig\" secondAttribute=\"leading\" id=\"2Ol-eL-6O3\"/>\n                <constraint firstAttribute=\"trailing\" secondItem=\"opJ-yV-dsw\" secondAttribute=\"trailing\" constant=\"79\" id=\"2uM-9u-piC\"/>\n                <constraint firstItem=\"dxs-EH-Lk0\" firstAttribute=\"leading\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"leading\" constant=\"16\" id=\"6pf-7c-Brw\"/>\n                <constraint firstItem=\"g6L-Vy-rKN\" firstAttribute=\"leading\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"leading\" constant=\"16\" id=\"77Y-g6-Kkt\"/>\n                <constraint firstItem=\"hBb-m4-Lg5\" firstAttribute=\"leading\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"leading\" constant=\"54\" id=\"9BI-dW-vak\"/>\n                <constraint firstItem=\"u4o-WA-mfN\" firstAttribute=\"leading\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"leading\" constant=\"16\" id=\"AZi-0E-5OF\"/>\n                <constraint firstItem=\"hBb-m4-Lg5\" firstAttribute=\"top\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"top\" constant=\"16\" id=\"B2c-4s-cEg\"/>\n                <constraint firstItem=\"g6L-Vy-rKN\" firstAttribute=\"top\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"top\" constant=\"54\" id=\"HaH-Ux-B0a\"/>\n                <constraint firstItem=\"Epz-1h-oTj\" firstAttribute=\"top\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"top\" constant=\"246\" id=\"NPI-k5-l4I\"/>\n                <constraint firstItem=\"opJ-yV-dsw\" firstAttribute=\"firstBaseline\" secondItem=\"UgL-8O-Ljc\" secondAttribute=\"firstBaseline\" id=\"Ncn-Xf-DUE\"/>\n                <constraint firstItem=\"mGa-dk-kQF\" firstAttribute=\"top\" secondItem=\"nB4-bN-Nk2\" secondAttribute=\"bottom\" constant=\"12\" id=\"QUv-uz-L7v\"/>\n                <constraint firstAttribute=\"trailing\" secondItem=\"g6L-Vy-rKN\" secondAttribute=\"trailing\" constant=\"16\" id=\"VMY-Hn-QCx\"/>\n                <constraint firstItem=\"opJ-yV-dsw\" firstAttribute=\"firstBaseline\" secondItem=\"nDP-xy-8Ig\" secondAttribute=\"firstBaseline\" id=\"ag5-Md-pvL\"/>\n                <constraint firstItem=\"dxs-EH-Lk0\" firstAttribute=\"top\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"top\" constant=\"10\" id=\"ar7-ls-sOf\"/>\n                <constraint firstItem=\"nB4-bN-Nk2\" firstAttribute=\"top\" secondItem=\"nDP-xy-8Ig\" secondAttribute=\"bottom\" constant=\"12\" id=\"bgT-lK-Vxz\"/>\n                <constraint firstAttribute=\"trailing\" secondItem=\"Epz-1h-oTj\" secondAttribute=\"trailing\" constant=\"16\" id=\"dl1-jL-Cpr\"/>\n                <constraint firstItem=\"hc3-Qt-NLz\" firstAttribute=\"top\" secondItem=\"mGa-dk-kQF\" secondAttribute=\"bottom\" constant=\"16\" id=\"eqb-c9-Zow\"/>\n                <constraint firstItem=\"Epz-1h-oTj\" firstAttribute=\"leading\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"leading\" constant=\"16\" id=\"iMu-N2-djD\"/>\n                <constraint firstItem=\"opJ-yV-dsw\" firstAttribute=\"leading\" secondItem=\"UgL-8O-Ljc\" secondAttribute=\"trailing\" constant=\"12\" symbolic=\"YES\" id=\"oH7-51-Jbt\"/>\n                <constraint firstItem=\"nB4-bN-Nk2\" firstAttribute=\"leading\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"leading\" constant=\"222\" id=\"pW7-Wt-Rqz\"/>\n                <constraint firstItem=\"u4o-WA-mfN\" firstAttribute=\"top\" secondItem=\"hc3-Qt-NLz\" secondAttribute=\"bottom\" constant=\"16\" id=\"pg5-tk-0nl\"/>\n                <constraint firstItem=\"nDP-xy-8Ig\" firstAttribute=\"top\" secondItem=\"g6L-Vy-rKN\" secondAttribute=\"bottom\" constant=\"16\" id=\"q68-nD-GdZ\"/>\n                <constraint firstItem=\"mGa-dk-kQF\" firstAttribute=\"leading\" secondItem=\"nDP-xy-8Ig\" secondAttribute=\"leading\" id=\"qjx-YJ-8tl\"/>\n                <constraint firstAttribute=\"trailing\" secondItem=\"u4o-WA-mfN\" secondAttribute=\"trailing\" constant=\"16\" id=\"rlc-RT-Qy3\"/>\n                <constraint firstAttribute=\"width\" relation=\"greaterThanOrEqual\" constant=\"800\" id=\"v8T-gL-Hvs\"/>\n            </constraints>\n            <point key=\"canvasLocation\" x=\"-478\" y=\"-828\"/>\n        </customView>\n    </objects>\n    <resources>\n        <image name=\"NSInfo\" width=\"32\" height=\"32\"/>\n        <image name=\"NSStatusAvailable\" width=\"16\" height=\"16\"/>\n        <image name=\"folder\" catalog=\"system\" width=\"18\" height=\"14\"/>\n        <image name=\"folder.badge.gearshape\" catalog=\"system\" width=\"19\" height=\"14\"/>\n        <image name=\"internaldrive\" catalog=\"system\" width=\"24\" height=\"17\"/>\n    </resources>\n</document>\n"
  },
  {
    "path": "Resources/MainUI/Settings panels/Collection View/PlayingCollectionViewItem.swift",
    "content": "//\n//  PlayingCollectionViewItem.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 18/11/2021.\n//  Copyright © 2021 Guillaume Louel. All rights reserved.\n//\n\nimport Cocoa\n\nclass PlayingCollectionViewItem: NSCollectionViewItem {\n    @IBOutlet var hiddenPath: NSTextField!\n    @IBOutlet var extraTextField: NSTextField!\n    \n    @IBOutlet var browseImageButton: NSButton!\n    @IBOutlet var mainImageButton: NSButton!\n    @IBOutlet var checkImageButton: NSButton!\n    \n    @IBOutlet var numberedPath: NSTextField!\n    \n    var nowPlayingViewController: NowPlayingViewController?\n    \n    override func viewDidLoad() {\n        super.viewDidLoad()\n        // For images the height coordinates are reversed, obviously...\n        let imgShadow: NSShadow = NSShadow()\n        imgShadow.shadowBlurRadius = 2\n        imgShadow.shadowOffset = NSSize(width: 0, height: 3)\n        imgShadow.shadowColor = NSColor.black\n        \n        browseImageButton.shadow = imgShadow\n        checkImageButton.shadow = imgShadow\n        // Do view setup here.\n    }\n    \n    \n    @IBAction func browseButton(_ sender: Any) {\n        Aerial.helper.windowController?.browseTo(hiddenPath.stringValue)\n    }\n    \n    @IBAction func mainImageClick(_ sender: NSButton) {\n        let path = hiddenPath.stringValue\n        \n        if checkImageButton.state == .on {\n            checkImageButton.state = .off\n            \n            checkImageButton.image = Aerial.helper.getSymbol(\"circle\")\n            if PrefsVideos.newShouldPlayString.contains(path) {\n                PrefsVideos.newShouldPlayString.remove(at: PrefsVideos.newShouldPlayString.firstIndex(of: path)!)\n            }\n            \n        } else {\n            checkImageButton.state = .on\n            \n            checkImageButton.image = Aerial.helper.getSymbol(\"checkmark.circle.fill\")\n            if !PrefsVideos.newShouldPlayString.contains(path) {\n                PrefsVideos.newShouldPlayString.append(path)\n            }\n            \n        }\n    }\n    @IBAction func imageButtonClick(_ sender: NSButton) {\n        let path = hiddenPath.stringValue\n        \n        if sender.state == .on {\n            sender.image = Aerial.helper.getSymbol(\"checkmark.circle.fill\")\n            if !PrefsVideos.newShouldPlayString.contains(path) {\n                PrefsVideos.newShouldPlayString.append(path)\n            }\n        } else {\n            sender.image = Aerial.helper.getSymbol(\"circle\")\n            if PrefsVideos.newShouldPlayString.contains(path) {\n                PrefsVideos.newShouldPlayString.remove(at: PrefsVideos.newShouldPlayString.firstIndex(of: path)!)\n            }\n        }\n    }\n    \n    /*   @IBAction func imageViewClick(_ sender: Any) {\n     print(\"click\")\n     let path = hiddenPath.stringValue\n     \n     \n     }*/\n    /*\n     @IBAction func checkButtonChange(_ sender: NSButton) {\n     let path = hiddenPath.stringValue\n     \n     if sender.state == .on {\n     if !PrefsVideos.newShouldPlayString.contains(path) {\n     PrefsVideos.newShouldPlayString.append(path)\n     }\n     } else {\n     if PrefsVideos.newShouldPlayString.contains(path) {\n     PrefsVideos.newShouldPlayString.remove(at: PrefsVideos.newShouldPlayString.firstIndex(of: path)!)\n     }\n     }\n     }*/\n    \n    \n    @IBAction func hideAllVideosClick(_ sender: NSMenuItem) {\n        let videos = VideoList.instance.getVideosForPath(numberedPath.stringValue)\n        \n        for video in videos.filter({ !PrefsVideos.hidden.contains($0.id) }) {\n            PrefsVideos.hidden.append(video.id)\n        }\n\n        VideoList.instance.reloadSources()\n    }\n    \n    @IBAction func favoriteAllClick(_ sender: Any) {\n        let videos = VideoList.instance.getVideosForPath(numberedPath.stringValue)\n\n        for video in videos.filter({ !PrefsVideos.favorites.contains($0.id) }) {\n            PrefsVideos.favorites.append(video.id)\n        }\n        VideoList.instance.reloadSources()\n    }\n\n    @IBAction func cacheVideosClick(_ sender: Any) {\n        Cache.ensureDownload {\n            let videos = VideoList.instance.getVideosForPath(self.numberedPath.stringValue)\n\n            for video in videos.filter({ !$0.isAvailableOffline }) {\n                VideoManager.sharedInstance.queueDownload(video)\n            }\n        }\n        VideoList.instance.reloadSources()\n    }\n    \n    @IBAction func unfavoriteAllClick(_ sender: Any) {\n        let videos = VideoList.instance.getVideosForPath(numberedPath.stringValue)\n\n        for video in videos.filter({ PrefsVideos.favorites.contains($0.id) }) {\n            PrefsVideos.favorites.remove(at: PrefsVideos.favorites.firstIndex(of: video.id)!)\n        }\n        VideoList.instance.reloadSources()\n    }\n    \n    @IBAction func resetVibranceClick(_ sender: Any) {\n        let videos = VideoList.instance.getVideosForPath(numberedPath.stringValue)\n\n        for video in videos.filter({ PrefsVideos.vibrance.keys.contains($0.id) }) {\n            PrefsVideos.vibrance.removeValue(forKey: video.id)\n        }\n    }\n    \n}\n"
  },
  {
    "path": "Resources/MainUI/Settings panels/Collection View/PlayingCollectionViewItem.xib",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.Cocoa.XIB\" version=\"3.0\" toolsVersion=\"21223\" targetRuntime=\"MacOSX.Cocoa\" propertyAccessControl=\"none\" useAutolayout=\"YES\" customObjectInstantitationMethod=\"direct\">\n    <dependencies>\n        <deployment identifier=\"macosx\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.CocoaPlugin\" version=\"21223\"/>\n        <capability name=\"Image references\" minToolsVersion=\"12.0\"/>\n        <capability name=\"documents saved in the Xcode 8 format\" minToolsVersion=\"8.0\"/>\n    </dependencies>\n    <objects>\n        <customObject id=\"-2\" userLabel=\"File's Owner\" customClass=\"PlayingCollectionViewItem\" customModule=\"Aerial\" customModuleProvider=\"target\">\n            <connections>\n                <outlet property=\"browseImageButton\" destination=\"V0d-fK-Vj1\" id=\"hzA-yY-Mve\"/>\n                <outlet property=\"checkImageButton\" destination=\"LDl-ex-q45\" id=\"Nb2-SB-JUn\"/>\n                <outlet property=\"extraTextField\" destination=\"bif-Gd-OGS\" id=\"Ixc-Nx-oNH\"/>\n                <outlet property=\"hiddenPath\" destination=\"egl-P1-lot\" id=\"EUQ-c0-rdQ\"/>\n                <outlet property=\"mainImageButton\" destination=\"Zi2-Qh-lVz\" id=\"7Yz-dq-93J\"/>\n                <outlet property=\"numberedPath\" destination=\"tH2-7d-IY5\" id=\"X3h-O4-9Bb\"/>\n                <outlet property=\"view\" destination=\"Hz6-mo-xeY\" id=\"0bl-1N-x8E\"/>\n            </connections>\n        </customObject>\n        <customObject id=\"-1\" userLabel=\"First Responder\" customClass=\"FirstResponder\"/>\n        <customObject id=\"-3\" userLabel=\"Application\" customClass=\"NSObject\"/>\n        <customView id=\"Hz6-mo-xeY\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"192\" height=\"149\"/>\n            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n            <subviews>\n                <button translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Zi2-Qh-lVz\">\n                    <rect key=\"frame\" x=\"0.0\" y=\"41\" width=\"192\" height=\"108\"/>\n                    <constraints>\n                        <constraint firstAttribute=\"height\" constant=\"108\" id=\"95D-IG-3Mq\"/>\n                        <constraint firstAttribute=\"width\" constant=\"192\" id=\"Idf-82-Vvf\"/>\n                    </constraints>\n                    <buttonCell key=\"cell\" type=\"square\" bezelStyle=\"shadowlessSquare\" imagePosition=\"only\" alignment=\"center\" imageScaling=\"proportionallyUpOrDown\" inset=\"2\" id=\"jtd-qB-G2G\">\n                        <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"mainImageClick:\" target=\"-2\" id=\"Bn8-8h-We2\"/>\n                    </connections>\n                </button>\n                <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"JBg-vZ-1fj\">\n                    <rect key=\"frame\" x=\"44\" y=\"20\" width=\"105\" height=\"19\"/>\n                    <textFieldCell key=\"cell\" scrollable=\"YES\" lineBreakMode=\"clipping\" title=\"San Francisco\" usesSingleLineMode=\"YES\" id=\"p6s-Zl-5wN\">\n                        <font key=\"font\" metaFont=\"systemSemibold\" size=\"15\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"bif-Gd-OGS\">\n                    <rect key=\"frame\" x=\"28\" y=\"2\" width=\"137\" height=\"16\"/>\n                    <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"15 videos, 40 minutes\" id=\"vlq-XP-lln\">\n                        <font key=\"font\" metaFont=\"system\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <textField hidden=\"YES\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"egl-P1-lot\">\n                    <rect key=\"frame\" x=\"34\" y=\"51\" width=\"37\" height=\"16\"/>\n                    <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                    <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" enabled=\"NO\" title=\"Label\" id=\"vS9-I4-FHx\">\n                        <font key=\"font\" usesAppearanceFont=\"YES\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <button toolTip=\"Browse those videos...\" verticalHuggingPriority=\"750\" misplaced=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"V0d-fK-Vj1\">\n                    <rect key=\"frame\" x=\"158\" y=\"118.5\" width=\"32.5\" height=\"27\"/>\n                    <buttonCell key=\"cell\" type=\"square\" bezelStyle=\"shadowlessSquare\" imagePosition=\"only\" alignment=\"center\" controlSize=\"large\" inset=\"2\" id=\"JLr-Jm-3Im\">\n                        <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\"/>\n                        <imageReference key=\"image\" image=\"arrowshape.turn.up.forward.fill\" catalog=\"system\" symbolScale=\"large\"/>\n                    </buttonCell>\n                    <color key=\"bezelColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"0.84705882349999995\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                    <color key=\"contentTintColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"0.84705882349999995\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                    <connections>\n                        <action selector=\"browseButton:\" target=\"-2\" id=\"5zI-eI-Yx5\"/>\n                    </connections>\n                </button>\n                <button translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"LDl-ex-q45\">\n                    <rect key=\"frame\" x=\"8\" y=\"47\" width=\"20\" height=\"26\"/>\n                    <constraints>\n                        <constraint firstAttribute=\"height\" constant=\"20\" id=\"9ts-Su-a27\"/>\n                        <constraint firstAttribute=\"width\" constant=\"20\" id=\"jIj-Df-dul\"/>\n                    </constraints>\n                    <buttonCell key=\"cell\" type=\"square\" bezelStyle=\"shadowlessSquare\" image=\"checkmark.circle.fill\" catalog=\"system\" imagePosition=\"only\" alignment=\"center\" controlSize=\"large\" state=\"on\" imageScaling=\"proportionallyUpOrDown\" inset=\"2\" id=\"8dZ-qN-YW6\">\n                        <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\"/>\n                    </buttonCell>\n                    <color key=\"contentTintColor\" white=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"genericGamma22GrayColorSpace\"/>\n                    <connections>\n                        <action selector=\"imageButtonClick:\" target=\"-2\" id=\"xEd-ji-0WU\"/>\n                    </connections>\n                </button>\n                <textField hidden=\"YES\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"tH2-7d-IY5\">\n                    <rect key=\"frame\" x=\"34\" y=\"75\" width=\"37\" height=\"16\"/>\n                    <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                    <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" enabled=\"NO\" title=\"Label\" id=\"JTu-lB-BSj\">\n                        <font key=\"font\" usesAppearanceFont=\"YES\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n            </subviews>\n            <constraints>\n                <constraint firstItem=\"JBg-vZ-1fj\" firstAttribute=\"centerX\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"centerX\" id=\"GOk-Jj-rSQ\"/>\n                <constraint firstItem=\"bif-Gd-OGS\" firstAttribute=\"centerX\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"centerX\" id=\"KaV-Tu-j3N\"/>\n                <constraint firstItem=\"Zi2-Qh-lVz\" firstAttribute=\"top\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"top\" id=\"V5q-sN-dCg\"/>\n                <constraint firstAttribute=\"trailing\" secondItem=\"V0d-fK-Vj1\" secondAttribute=\"trailing\" constant=\"8\" id=\"VMd-0O-066\"/>\n                <constraint firstItem=\"JBg-vZ-1fj\" firstAttribute=\"top\" secondItem=\"Zi2-Qh-lVz\" secondAttribute=\"bottom\" constant=\"2\" id=\"Xtq-9W-pP8\"/>\n                <constraint firstItem=\"LDl-ex-q45\" firstAttribute=\"leading\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"leading\" constant=\"8\" id=\"eii-cf-0Jf\"/>\n                <constraint firstItem=\"V0d-fK-Vj1\" firstAttribute=\"top\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"top\" constant=\"8\" id=\"hJy-tD-aGu\"/>\n                <constraint firstAttribute=\"bottom\" secondItem=\"LDl-ex-q45\" secondAttribute=\"bottom\" constant=\"50\" id=\"izV-H6-PGl\"/>\n                <constraint firstItem=\"bif-Gd-OGS\" firstAttribute=\"top\" secondItem=\"JBg-vZ-1fj\" secondAttribute=\"bottom\" constant=\"2\" id=\"pAJ-oY-AjH\"/>\n                <constraint firstItem=\"Zi2-Qh-lVz\" firstAttribute=\"leading\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"leading\" id=\"r11-Li-PgF\"/>\n            </constraints>\n            <connections>\n                <outlet property=\"menu\" destination=\"ljy-gl-3bd\" id=\"Ogf-nb-Dlh\"/>\n            </connections>\n            <point key=\"canvasLocation\" x=\"233\" y=\"115.5\"/>\n        </customView>\n        <collectionViewItem id=\"3Ba-YT-RGC\" customClass=\"PlayingCollectionViewItem\" customModule=\"Aerial\" customModuleProvider=\"target\">\n            <connections>\n                <outlet property=\"browseImageButton\" destination=\"V0d-fK-Vj1\" id=\"dLn-ag-pb2\"/>\n                <outlet property=\"checkImageButton\" destination=\"LDl-ex-q45\" id=\"uRT-GH-jzi\"/>\n                <outlet property=\"extraTextField\" destination=\"bif-Gd-OGS\" id=\"pQc-9y-OGV\"/>\n                <outlet property=\"hiddenPath\" destination=\"egl-P1-lot\" id=\"vqp-1L-Tfr\"/>\n                <outlet property=\"mainImageButton\" destination=\"Zi2-Qh-lVz\" id=\"tCW-a9-IJA\"/>\n                <outlet property=\"numberedPath\" destination=\"tH2-7d-IY5\" id=\"FAg-KK-siE\"/>\n                <outlet property=\"sourceItemView\" destination=\"Zi2-Qh-lVz\" id=\"A18-1N-VFR\"/>\n                <outlet property=\"textField\" destination=\"JBg-vZ-1fj\" id=\"VvQ-u0-WQM\"/>\n                <outlet property=\"view\" destination=\"Hz6-mo-xeY\" id=\"2XE-5s-UIH\"/>\n            </connections>\n        </collectionViewItem>\n        <menu id=\"ljy-gl-3bd\">\n            <items>\n                <menuItem title=\"Cache missing videos\" image=\"arrow.down.circle\" catalog=\"system\" id=\"cih-PU-uqp\">\n                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                    <connections>\n                        <action selector=\"cacheVideosClick:\" target=\"-2\" id=\"mvV-we-yFD\"/>\n                    </connections>\n                </menuItem>\n                <menuItem isSeparatorItem=\"YES\" id=\"i4P-jv-Bfy\"/>\n                <menuItem title=\"Hide all videos\" image=\"eye.slash\" catalog=\"system\" id=\"Xe2-S5-Mra\">\n                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                    <connections>\n                        <action selector=\"hideAllVideosClick:\" target=\"-2\" id=\"d7g-Nm-oDH\"/>\n                    </connections>\n                </menuItem>\n                <menuItem isSeparatorItem=\"YES\" id=\"tYx-UV-zzI\"/>\n                <menuItem title=\"Favorite all videos\" image=\"star.fill\" catalog=\"system\" id=\"D8t-IU-GG1\">\n                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                    <connections>\n                        <action selector=\"favoriteAllClick:\" target=\"-2\" id=\"Lwv-B7-QEU\"/>\n                    </connections>\n                </menuItem>\n                <menuItem title=\"Unfavorite all videos\" image=\"star.slash\" catalog=\"system\" id=\"97z-Jk-eGb\">\n                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                    <connections>\n                        <action selector=\"unfavoriteAllClick:\" target=\"-2\" id=\"Rcj-2h-3qW\"/>\n                    </connections>\n                </menuItem>\n                <menuItem isSeparatorItem=\"YES\" id=\"OPm-ID-e9x\"/>\n                <menuItem title=\"Reset vibrance\" image=\"slider.horizontal.3\" catalog=\"system\" id=\"lcy-LJ-CyX\">\n                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                    <connections>\n                        <action selector=\"resetVibranceClick:\" target=\"-2\" id=\"G2g-ov-221\"/>\n                    </connections>\n                </menuItem>\n            </items>\n            <point key=\"canvasLocation\" x=\"314\" y=\"382\"/>\n        </menu>\n    </objects>\n    <resources>\n        <image name=\"arrow.down.circle\" catalog=\"system\" width=\"15\" height=\"15\"/>\n        <image name=\"arrowshape.turn.up.forward.fill\" catalog=\"system\" width=\"21\" height=\"18\"/>\n        <image name=\"checkmark.circle.fill\" catalog=\"system\" width=\"15\" height=\"15\"/>\n        <image name=\"eye.slash\" catalog=\"system\" width=\"21\" height=\"14\"/>\n        <image name=\"slider.horizontal.3\" catalog=\"system\" width=\"16\" height=\"13\"/>\n        <image name=\"star.fill\" catalog=\"system\" width=\"17\" height=\"16\"/>\n        <image name=\"star.slash\" catalog=\"system\" width=\"17\" height=\"16\"/>\n    </resources>\n</document>\n"
  },
  {
    "path": "Resources/MainUI/Settings panels/CompanionCacheViewController.swift",
    "content": "//\n//  CompanionCacheViewController.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 17/07/2022.\n//  Copyright © 2022 Guillaume Louel. All rights reserved.\n//\n\nimport Cocoa\n\nclass CompanionCacheViewController: NSViewController {\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n        // Do view setup here.\n    }\n    \n    @IBAction func openSystemPreferences(_ sender: Any) {\n        if #available(macOS 13, *) {\n            _ = Aerial.helper.shell(launchPath: \"/usr/bin/open\", arguments: [\"x-apple.systempreferences:com.apple.ScreenSaver-Settings.extension\"])\n        } else {\n            _ = Aerial.helper.shell(launchPath: \"/usr/bin/osascript\", arguments: [\n            \"-e\", \"tell application \\\"System Preferences\\\"\",\n            \"-e\",\"set the current pane to pane id \\\"com.apple.preference.desktopscreeneffect\\\"\",\n            \"-e\",\"reveal anchor \\\"ScreenSaverPref\\\" of pane id \\\"com.apple.preference.desktopscreeneffect\\\"\",\n            \"-e\",\"activate\",\n            \"-e\",\"end tell\"])\n\n        }\n    }\n}\n"
  },
  {
    "path": "Resources/MainUI/Settings panels/CompanionCacheViewController.xib",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.Cocoa.XIB\" version=\"3.0\" toolsVersion=\"22154\" targetRuntime=\"MacOSX.Cocoa\" propertyAccessControl=\"none\" useAutolayout=\"YES\" customObjectInstantitationMethod=\"direct\">\n    <dependencies>\n        <deployment identifier=\"macosx\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.CocoaPlugin\" version=\"22154\"/>\n        <capability name=\"documents saved in the Xcode 8 format\" minToolsVersion=\"8.0\"/>\n    </dependencies>\n    <objects>\n        <customObject id=\"-2\" userLabel=\"File's Owner\" customClass=\"CompanionCacheViewController\" customModule=\"Aerial\" customModuleProvider=\"target\">\n            <connections>\n                <outlet property=\"view\" destination=\"Hz6-mo-xeY\" id=\"0bl-1N-x8E\"/>\n            </connections>\n        </customObject>\n        <customObject id=\"-1\" userLabel=\"First Responder\" customClass=\"FirstResponder\"/>\n        <customObject id=\"-3\" userLabel=\"Application\" customClass=\"NSObject\"/>\n        <customView translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Hz6-mo-xeY\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"811\" height=\"530\"/>\n            <subviews>\n                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"ifs-Lr-XlU\">\n                    <rect key=\"frame\" x=\"142\" y=\"339\" width=\"528\" height=\"16\"/>\n                    <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"To change your cache settings, please access Aerial's settings via System Preferences\" id=\"a0c-vr-D73\">\n                        <font key=\"font\" metaFont=\"system\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"38f-Ki-Icd\">\n                    <rect key=\"frame\" x=\"311\" y=\"285\" width=\"190\" height=\"40\"/>\n                    <buttonCell key=\"cell\" type=\"push\" title=\"Open System Preferences\" bezelStyle=\"rounded\" alignment=\"center\" controlSize=\"large\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"WuG-oo-mFk\">\n                        <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"openSystemPreferences:\" target=\"-2\" id=\"wat-Qb-9xb\"/>\n                    </connections>\n                </button>\n            </subviews>\n            <constraints>\n                <constraint firstItem=\"ifs-Lr-XlU\" firstAttribute=\"centerX\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"centerX\" id=\"7FL-iI-jMX\"/>\n                <constraint firstAttribute=\"width\" relation=\"greaterThanOrEqual\" constant=\"811\" id=\"7uR-PI-bMj\"/>\n                <constraint firstItem=\"38f-Ki-Icd\" firstAttribute=\"centerX\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"centerX\" id=\"JmB-Sn-2Oh\"/>\n                <constraint firstAttribute=\"height\" relation=\"greaterThanOrEqual\" constant=\"530\" id=\"Wqe-5k-esa\"/>\n                <constraint firstItem=\"ifs-Lr-XlU\" firstAttribute=\"top\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"top\" constant=\"175\" id=\"XU0-qH-3zJ\"/>\n                <constraint firstItem=\"38f-Ki-Icd\" firstAttribute=\"top\" secondItem=\"ifs-Lr-XlU\" secondAttribute=\"bottom\" constant=\"20\" id=\"wdU-ZN-8fP\"/>\n            </constraints>\n            <point key=\"canvasLocation\" x=\"237.5\" y=\"239.5\"/>\n        </customView>\n    </objects>\n</document>\n"
  },
  {
    "path": "Resources/MainUI/Settings panels/DisplaysViewController.swift",
    "content": "//\n//  DisplaysViewController.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 18/07/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Cocoa\n\nclass DisplaysViewController: NSViewController {\n    @IBOutlet var displayView: DisplayView!\n    @IBOutlet var displayInstructionLabel: NSTextField!\n\n    @IBOutlet var displayPopup: NSPopUpButton!\n    @IBOutlet var viewingModePopup: NSPopUpButton!\n    @IBOutlet var aspectPopup: NSPopUpButton!\n\n    @IBOutlet var marginBox: NSBox!\n    @IBOutlet var horizontalMarginTextField: NSTextField!\n    @IBOutlet var verticalMarginTextField: NSTextField!\n    @IBOutlet var advancedMode: NSButton!\n    @IBOutlet var advancedModeEdit: NSButton!\n\n    // Advanced margin edit panel\n    @IBOutlet var advancedEditPanel: NSPanel!\n    @IBOutlet var advancedEditPanelTextfield: NSTextField!\n    @IBOutlet var advancedEditApply: NSButton!\n    @IBOutlet var advancedApplyClose: NSButton!\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n\n        // This is the label in the large display view in the top\n        if PrefsDisplays.displayMode == .selection {\n            displayInstructionLabel.isHidden = false\n        }\n\n        // Popups\n        displayPopup.selectItem(at: PrefsDisplays.displayMode.rawValue)\n        viewingModePopup.selectItem(at: PrefsDisplays.viewingMode.rawValue)\n        aspectPopup.selectItem(at: PrefsDisplays.aspectMode.rawValue)\n\n        // Margins\n        if PrefsDisplays.viewingMode == .spanned {\n            marginBox.isHidden = false\n        } else {\n            marginBox.isHidden = true\n        }\n\n        if PrefsDisplays.displayMarginsAdvanced {\n            advancedMode.state = .on\n            advancedModeEdit.isEnabled = true\n        } else {\n            advancedMode.state = .off\n            advancedModeEdit.isEnabled = false\n        }\n\n        horizontalMarginTextField.doubleValue = PrefsDisplays.horizontalMargin\n        verticalMarginTextField.doubleValue = PrefsDisplays.verticalMargin\n    }\n\n    @IBAction func displayPopupChange(_ sender: NSPopUpButton) {\n        PrefsDisplays.displayMode = DisplayMode(rawValue: sender.indexOfSelectedItem)!\n        if PrefsDisplays.displayMode == .selection {\n            displayInstructionLabel.isHidden = false\n        } else {\n            displayInstructionLabel.isHidden = true\n        }\n        displayView.needsDisplay = true\n    }\n\n    @IBAction func viewingModeChange(_ sender: NSPopUpButton) {\n        PrefsDisplays.viewingMode = ViewingMode(rawValue: sender.indexOfSelectedItem)!\n        DisplayDetection.sharedInstance.detectDisplays()   // Force redetection to update our margin calculations in spanned mode\n        displayView.needsDisplay = true\n\n        if PrefsDisplays.viewingMode == .spanned {\n            marginBox.isHidden = false\n        } else {\n            marginBox.isHidden = true\n        }\n    }\n\n    @IBAction func aspectPopupChange(_ sender: NSPopUpButton) {\n        PrefsDisplays.aspectMode = AspectMode(rawValue: sender.indexOfSelectedItem)!\n    }\n\n    @IBAction func horizontalMarginChange(_ sender: NSTextField) {\n        PrefsDisplays.horizontalMargin = sender.doubleValue\n\n        DisplayDetection.sharedInstance.detectDisplays()   // Force redetection to update our margin calculations in spanned mode\n        displayView.needsDisplay = true\n    }\n\n    @IBAction func verticalMarginChange(_ sender: NSTextField) {\n        PrefsDisplays.verticalMargin = sender.doubleValue\n\n        DisplayDetection.sharedInstance.detectDisplays()   // Force redetection to update our margin calculations in spanned mode\n        displayView.needsDisplay = true\n    }\n\n    @IBAction func advancedModeClick(_ sender: NSButton) {\n        PrefsDisplays.displayMarginsAdvanced = sender.state == .on\n        if PrefsDisplays.displayMarginsAdvanced {\n            advancedModeEdit.isEnabled = true\n        } else {\n            advancedModeEdit.isEnabled = false\n        }\n        displayView.needsDisplay = true\n    }\n\n    // Advanced margins panel\n    @IBAction func advancedModeEditClick(_ sender: Any) {\n        if advancedEditPanel.isVisible {\n            advancedEditPanel.close()\n        } else {\n            // Grab the JSON\n            advancedEditPanelTextfield.stringValue = DisplayDetection.sharedInstance.getMarginsJSON()\n\n            advancedEditPanel.makeKeyAndOrderFront(sender)\n        }\n    }\n\n    @IBAction func advancedModePanelApply(_ sender: Any) {\n        // We save the JSON as String\n        PrefsDisplays.advancedMargins = advancedEditPanelTextfield.stringValue\n\n        // And redetect\n        DisplayDetection.sharedInstance.detectDisplays()   // Force redetection to update our margin calculations in spanned mode\n        displayView.needsDisplay = true\n    }\n\n    @IBAction func advancedModePanelApplyClose(_ sender: Any) {\n        // We save the JSON as String\n        PrefsDisplays.advancedMargins = advancedEditPanelTextfield.stringValue\n\n        // And redetect\n        DisplayDetection.sharedInstance.detectDisplays()   // Force redetection to update our margin calculations in spanned mode\n        displayView.needsDisplay = true\n        advancedEditPanel.close()\n    }\n}\n"
  },
  {
    "path": "Resources/MainUI/Settings panels/DisplaysViewController.xib",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.Cocoa.XIB\" version=\"3.0\" toolsVersion=\"22113.1\" targetRuntime=\"MacOSX.Cocoa\" propertyAccessControl=\"none\" useAutolayout=\"YES\" customObjectInstantitationMethod=\"direct\">\n    <dependencies>\n        <deployment identifier=\"macosx\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.CocoaPlugin\" version=\"22113.1\"/>\n        <capability name=\"Image references\" minToolsVersion=\"12.0\"/>\n        <capability name=\"System colors introduced in macOS 10.14\" minToolsVersion=\"10.0\"/>\n        <capability name=\"documents saved in the Xcode 8 format\" minToolsVersion=\"8.0\"/>\n    </dependencies>\n    <objects>\n        <customObject id=\"-2\" userLabel=\"File's Owner\" customClass=\"DisplaysViewController\" customModule=\"Aerial\" customModuleProvider=\"target\">\n            <connections>\n                <outlet property=\"advancedApplyClose\" destination=\"3GO-u2-6hd\" id=\"WM3-P2-PRP\"/>\n                <outlet property=\"advancedEditApply\" destination=\"rfs-OT-GE7\" id=\"EpL-gl-EgP\"/>\n                <outlet property=\"advancedEditPanel\" destination=\"I9Z-Fv-GnD\" id=\"yTC-wS-Drd\"/>\n                <outlet property=\"advancedEditPanelTextfield\" destination=\"Whr-Ke-RvG\" id=\"UMS-CN-DjH\"/>\n                <outlet property=\"advancedMode\" destination=\"euP-3J-lWH\" id=\"dRP-HJ-kyK\"/>\n                <outlet property=\"advancedModeEdit\" destination=\"PU4-Gc-gVh\" id=\"551-nw-AXC\"/>\n                <outlet property=\"aspectPopup\" destination=\"PYx-68-4kx\" id=\"Asu-79-aVY\"/>\n                <outlet property=\"displayInstructionLabel\" destination=\"983-Z5-Mab\" id=\"mlb-pn-kxl\"/>\n                <outlet property=\"displayPopup\" destination=\"qfZ-Cq-UaC\" id=\"dmd-0b-Z9o\"/>\n                <outlet property=\"displayView\" destination=\"n6K-Mt-UWg\" id=\"lc0-qf-Oln\"/>\n                <outlet property=\"horizontalMarginTextField\" destination=\"K2l-e4-wXg\" id=\"ddg-tF-OP8\"/>\n                <outlet property=\"marginBox\" destination=\"Ox7-1B-gOB\" id=\"dc6-eT-3FE\"/>\n                <outlet property=\"verticalMarginTextField\" destination=\"7bY-na-F0E\" id=\"gqL-jY-qyJ\"/>\n                <outlet property=\"view\" destination=\"Hz6-mo-xeY\" id=\"0bl-1N-x8E\"/>\n                <outlet property=\"viewingModePopup\" destination=\"sZh-ot-4zc\" id=\"a4C-dZ-eO2\"/>\n            </connections>\n        </customObject>\n        <customObject id=\"-1\" userLabel=\"First Responder\" customClass=\"FirstResponder\"/>\n        <customObject id=\"-3\" userLabel=\"Application\" customClass=\"NSObject\"/>\n        <customView translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Hz6-mo-xeY\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"811\" height=\"530\"/>\n            <subviews>\n                <customView toolTip=\"DisplayView\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"n6K-Mt-UWg\" customClass=\"DisplayView\" customModule=\"Aerial\" customModuleProvider=\"target\">\n                    <rect key=\"frame\" x=\"16\" y=\"217\" width=\"779\" height=\"259\"/>\n                    <subviews>\n                        <textField hidden=\"YES\" focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"983-Z5-Mab\">\n                            <rect key=\"frame\" x=\"290\" y=\"237\" width=\"200\" height=\"14\"/>\n                            <constraints>\n                                <constraint firstAttribute=\"height\" constant=\"14\" id=\"zjv-5D-fbO\"/>\n                            </constraints>\n                            <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"Click on a Display to enable/disable it\" id=\"F1d-yt-ag6\">\n                                <font key=\"font\" metaFont=\"message\" size=\"11\"/>\n                                <color key=\"textColor\" name=\"secondaryLabelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                            </textFieldCell>\n                        </textField>\n                    </subviews>\n                    <constraints>\n                        <constraint firstItem=\"983-Z5-Mab\" firstAttribute=\"top\" secondItem=\"n6K-Mt-UWg\" secondAttribute=\"top\" constant=\"8\" id=\"4x3-Ig-md6\"/>\n                        <constraint firstItem=\"983-Z5-Mab\" firstAttribute=\"centerX\" secondItem=\"n6K-Mt-UWg\" secondAttribute=\"centerX\" id=\"kmc-mY-gda\"/>\n                        <constraint firstAttribute=\"height\" constant=\"259\" id=\"nsR-Q2-p1V\"/>\n                    </constraints>\n                </customView>\n                <popUpButton verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"qfZ-Cq-UaC\">\n                    <rect key=\"frame\" x=\"163\" y=\"133\" width=\"180\" height=\"40\"/>\n                    <popUpButtonCell key=\"cell\" type=\"push\" title=\"All displays\" bezelStyle=\"rounded\" alignment=\"left\" controlSize=\"large\" lineBreakMode=\"truncatingTail\" state=\"on\" borderStyle=\"borderAndBezel\" imageScaling=\"proportionallyDown\" inset=\"2\" selectedItem=\"J2E-qR-udk\" id=\"v0d-RM-MCU\">\n                        <behavior key=\"behavior\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" size=\"14\" name=\"HelveticaNeue\"/>\n                        <menu key=\"menu\" id=\"bev-YH-Xgu\">\n                            <items>\n                                <menuItem title=\"All displays\" state=\"on\" id=\"J2E-qR-udk\"/>\n                                <menuItem title=\"Main display\" id=\"RUN-Re-L3l\">\n                                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                </menuItem>\n                                <menuItem title=\"Secondary display(s)\" id=\"oUF-yP-Tvf\">\n                                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                </menuItem>\n                                <menuItem title=\"Selected displays\" id=\"Cdo-YL-6JD\"/>\n                            </items>\n                        </menu>\n                    </popUpButtonCell>\n                    <connections>\n                        <action selector=\"displayPopupChange:\" target=\"-2\" id=\"vLI-sV-7PO\"/>\n                    </connections>\n                </popUpButton>\n                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"FYf-yB-Ksg\">\n                    <rect key=\"frame\" x=\"62\" y=\"96\" width=\"100\" height=\"17\"/>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" alignment=\"right\" title=\"Viewing mode:\" id=\"f4X-5n-eo8\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <popUpButton verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"sZh-ot-4zc\">\n                    <rect key=\"frame\" x=\"163\" y=\"83\" width=\"129\" height=\"40\"/>\n                    <popUpButtonCell key=\"cell\" type=\"push\" title=\"Independent\" bezelStyle=\"rounded\" alignment=\"left\" controlSize=\"large\" lineBreakMode=\"truncatingTail\" state=\"on\" borderStyle=\"borderAndBezel\" imageScaling=\"proportionallyDown\" inset=\"2\" selectedItem=\"KIf-sb-Emv\" id=\"cV2-eN-5od\">\n                        <behavior key=\"behavior\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" size=\"14\" name=\"HelveticaNeue\"/>\n                        <menu key=\"menu\" id=\"nrL-vd-cjC\">\n                            <items>\n                                <menuItem title=\"Independent\" state=\"on\" id=\"KIf-sb-Emv\"/>\n                                <menuItem title=\"Cloned\" id=\"Z9k-Ly-6n7\" userLabel=\"Cloned\">\n                                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                </menuItem>\n                                <menuItem title=\"Spanned\" id=\"bRN-CT-W01\">\n                                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                </menuItem>\n                                <menuItem title=\"Mirrored\" id=\"ngO-m3-QJm\" userLabel=\"Mirrored\">\n                                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                </menuItem>\n                            </items>\n                        </menu>\n                    </popUpButtonCell>\n                    <connections>\n                        <action selector=\"viewingModeChange:\" target=\"-2\" id=\"o1A-FR-5uA\"/>\n                    </connections>\n                </popUpButton>\n                <popUpButton verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"PYx-68-4kx\">\n                    <rect key=\"frame\" x=\"163\" y=\"33\" width=\"128\" height=\"40\"/>\n                    <popUpButtonCell key=\"cell\" type=\"push\" title=\"Fill screen\" bezelStyle=\"rounded\" alignment=\"left\" controlSize=\"large\" lineBreakMode=\"truncatingTail\" state=\"on\" borderStyle=\"borderAndBezel\" imageScaling=\"proportionallyDown\" inset=\"2\" selectedItem=\"dj2-Xj-C0G\" id=\"dcB-Z0-gWg\">\n                        <behavior key=\"behavior\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" size=\"14\" name=\"HelveticaNeue\"/>\n                        <menu key=\"menu\" id=\"FW6-yi-6sC\">\n                            <items>\n                                <menuItem title=\"Fill screen\" state=\"on\" id=\"dj2-Xj-C0G\"/>\n                                <menuItem title=\"Fit to screen\" id=\"O8c-m3-hfx\"/>\n                            </items>\n                        </menu>\n                    </popUpButtonCell>\n                    <connections>\n                        <action selector=\"aspectPopupChange:\" target=\"-2\" id=\"UcG-TD-Ktk\"/>\n                    </connections>\n                </popUpButton>\n                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"eyI-Yg-cqz\">\n                    <rect key=\"frame\" x=\"108\" y=\"46\" width=\"54\" height=\"17\"/>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" alignment=\"right\" title=\"Aspect:\" id=\"YPL-NK-wIy\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"8QF-Al-Xli\">\n                    <rect key=\"frame\" x=\"44\" y=\"189\" width=\"441\" height=\"17\"/>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" title=\"You can modify your arrangement in System Preferences &gt; Displays\" id=\"YxN-bQ-RUv\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"secondaryLabelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Oei-up-hVB\">\n                    <rect key=\"frame\" x=\"61\" y=\"146\" width=\"101\" height=\"17\"/>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" alignment=\"right\" title=\"Play videos on:\" id=\"4TF-Mn-3wq\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <imageView horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"cMW-Uc-M4F\">\n                    <rect key=\"frame\" x=\"16\" y=\"186\" width=\"22\" height=\"22\"/>\n                    <constraints>\n                        <constraint firstAttribute=\"height\" constant=\"22\" id=\"gwh-i6-p9f\"/>\n                        <constraint firstAttribute=\"width\" constant=\"22\" id=\"uma-pt-Hb1\"/>\n                    </constraints>\n                    <imageCell key=\"cell\" controlSize=\"large\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" image=\"NSInfo\" id=\"eeo-Ti-feW\"/>\n                </imageView>\n                <imageView horizontalHuggingPriority=\"25\" verticalHuggingPriority=\"25\" horizontalCompressionResistancePriority=\"75\" verticalCompressionResistancePriority=\"75\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"JFQ-iQ-S3H\">\n                    <rect key=\"frame\" x=\"16\" y=\"480.5\" width=\"28\" height=\"45\"/>\n                    <constraints>\n                        <constraint firstAttribute=\"width\" constant=\"28\" id=\"KLi-KE-E9I\"/>\n                    </constraints>\n                    <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyUpOrDown\" id=\"6lr-CG-PQN\">\n                        <imageReference key=\"image\" image=\"display.2\" catalog=\"system\" symbolScale=\"large\"/>\n                    </imageCell>\n                    <color key=\"contentTintColor\" name=\"controlAccentColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                </imageView>\n                <textField focusRingType=\"none\" horizontalCompressionResistancePriority=\"250\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"OK0-JG-81Q\">\n                    <rect key=\"frame\" x=\"52\" y=\"497\" width=\"324\" height=\"17\"/>\n                    <textFieldCell key=\"cell\" selectable=\"YES\" title=\"You can decide where and how videos will appear\" id=\"jgO-Y5-EzE\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <box fixedFrame=\"YES\" boxType=\"secondary\" title=\"Margins between screens\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Ox7-1B-gOB\">\n                    <rect key=\"frame\" x=\"470\" y=\"28\" width=\"328\" height=\"150\"/>\n                    <autoresizingMask key=\"autoresizingMask\" flexibleMinX=\"YES\" flexibleMinY=\"YES\"/>\n                    <view key=\"contentView\" id=\"VVm-6p-iL2\">\n                        <rect key=\"frame\" x=\"4\" y=\"5\" width=\"320\" height=\"127\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <subviews>\n                            <textField focusRingType=\"none\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"K2l-e4-wXg\">\n                                <rect key=\"frame\" x=\"115\" y=\"90\" width=\"61\" height=\"22\"/>\n                                <constraints>\n                                    <constraint firstAttribute=\"width\" constant=\"61\" id=\"Yg3-FV-PJC\"/>\n                                </constraints>\n                                <textFieldCell key=\"cell\" controlSize=\"large\" scrollable=\"YES\" lineBreakMode=\"clipping\" selectable=\"YES\" editable=\"YES\" sendsActionOnEndEditing=\"YES\" borderStyle=\"bezel\" drawsBackground=\"YES\" id=\"DBh-yG-XhJ\">\n                                    <numberFormatter key=\"formatter\" formatterBehavior=\"default10_4\" numberStyle=\"decimal\" minimumIntegerDigits=\"1\" maximumIntegerDigits=\"2000000000\" maximumFractionDigits=\"3\" id=\"Bt4-A2-XSi\"/>\n                                    <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                    <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                </textFieldCell>\n                                <connections>\n                                    <action selector=\"horizontalMarginChange:\" target=\"-2\" id=\"tuN-6n-56h\"/>\n                                </connections>\n                            </textField>\n                            <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"SZR-32-kbI\">\n                                <rect key=\"frame\" x=\"182\" y=\"92\" width=\"24\" height=\"17\"/>\n                                <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" title=\"cm\" id=\"eBX-Cs-SPi\">\n                                    <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                    <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                </textFieldCell>\n                            </textField>\n                            <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"SdT-xC-Llf\">\n                                <rect key=\"frame\" x=\"52\" y=\"55\" width=\"57\" height=\"17\"/>\n                                <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" alignment=\"right\" title=\"Vertical:\" id=\"xLc-oZ-hEe\">\n                                    <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                    <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                </textFieldCell>\n                            </textField>\n                            <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Zts-Q2-7Ll\">\n                                <rect key=\"frame\" x=\"181\" y=\"55\" width=\"24\" height=\"17\"/>\n                                <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" title=\"cm\" id=\"Xao-E6-too\">\n                                    <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                    <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                </textFieldCell>\n                            </textField>\n                            <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"8nk-DS-uQp\">\n                                <rect key=\"frame\" x=\"34\" y=\"92\" width=\"75\" height=\"17\"/>\n                                <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" alignment=\"right\" title=\"Horizontal:\" id=\"IeL-ls-5p3\">\n                                    <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                    <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                </textFieldCell>\n                            </textField>\n                            <textField focusRingType=\"none\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"7bY-na-F0E\">\n                                <rect key=\"frame\" x=\"115\" y=\"53\" width=\"60\" height=\"22\"/>\n                                <constraints>\n                                    <constraint firstAttribute=\"width\" constant=\"60\" id=\"MsW-uW-zyf\"/>\n                                </constraints>\n                                <textFieldCell key=\"cell\" controlSize=\"large\" scrollable=\"YES\" lineBreakMode=\"clipping\" selectable=\"YES\" editable=\"YES\" sendsActionOnEndEditing=\"YES\" borderStyle=\"bezel\" drawsBackground=\"YES\" id=\"6ij-1a-7XP\">\n                                    <numberFormatter key=\"formatter\" formatterBehavior=\"default10_4\" numberStyle=\"decimal\" minimumIntegerDigits=\"1\" maximumIntegerDigits=\"2000000000\" maximumFractionDigits=\"3\" id=\"2PC-go-brb\"/>\n                                    <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                    <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                </textFieldCell>\n                                <connections>\n                                    <action selector=\"verticalMarginChange:\" target=\"-2\" id=\"5hN-AH-o5I\"/>\n                                </connections>\n                            </textField>\n                            <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"PU4-Gc-gVh\">\n                                <rect key=\"frame\" x=\"248\" y=\"8\" width=\"69\" height=\"40\"/>\n                                <buttonCell key=\"cell\" type=\"push\" title=\"Edit...\" bezelStyle=\"rounded\" alignment=\"center\" controlSize=\"large\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"dq0-30-Ees\">\n                                    <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                                    <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                </buttonCell>\n                                <connections>\n                                    <action selector=\"advancedModeEditClick:\" target=\"-2\" id=\"Sss-ht-DSc\"/>\n                                </connections>\n                            </button>\n                            <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"euP-3J-lWH\">\n                                <rect key=\"frame\" x=\"112\" y=\"18.5\" width=\"134\" height=\"22\"/>\n                                <buttonCell key=\"cell\" type=\"check\" title=\"Advanced mode\" bezelStyle=\"regularSquare\" imagePosition=\"left\" controlSize=\"large\" state=\"on\" inset=\"2\" id=\"ztY-UW-EWe\">\n                                    <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                                    <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                </buttonCell>\n                                <connections>\n                                    <action selector=\"advancedModeClick:\" target=\"-2\" id=\"6Li-8e-dYZ\"/>\n                                </connections>\n                            </button>\n                        </subviews>\n                        <constraints>\n                            <constraint firstItem=\"SZR-32-kbI\" firstAttribute=\"leading\" secondItem=\"K2l-e4-wXg\" secondAttribute=\"trailing\" constant=\"8\" id=\"3Oh-zS-V5v\"/>\n                            <constraint firstItem=\"7bY-na-F0E\" firstAttribute=\"firstBaseline\" secondItem=\"SdT-xC-Llf\" secondAttribute=\"firstBaseline\" id=\"8pg-C0-s6D\"/>\n                            <constraint firstItem=\"K2l-e4-wXg\" firstAttribute=\"leading\" secondItem=\"8nk-DS-uQp\" secondAttribute=\"trailing\" constant=\"8\" id=\"Axc-4T-zpa\"/>\n                            <constraint firstItem=\"Zts-Q2-7Ll\" firstAttribute=\"firstBaseline\" secondItem=\"SdT-xC-Llf\" secondAttribute=\"firstBaseline\" id=\"Ghc-d4-1bD\"/>\n                            <constraint firstItem=\"PU4-Gc-gVh\" firstAttribute=\"leading\" secondItem=\"euP-3J-lWH\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"Ii5-3X-aiF\"/>\n                            <constraint firstItem=\"K2l-e4-wXg\" firstAttribute=\"firstBaseline\" secondItem=\"8nk-DS-uQp\" secondAttribute=\"firstBaseline\" id=\"OJh-wn-7Og\"/>\n                            <constraint firstItem=\"7bY-na-F0E\" firstAttribute=\"leading\" secondItem=\"VVm-6p-iL2\" secondAttribute=\"leading\" constant=\"115\" id=\"Ptq-B8-X19\"/>\n                            <constraint firstItem=\"K2l-e4-wXg\" firstAttribute=\"top\" secondItem=\"VVm-6p-iL2\" secondAttribute=\"top\" constant=\"15\" id=\"QqL-rt-sXl\"/>\n                            <constraint firstItem=\"K2l-e4-wXg\" firstAttribute=\"leading\" secondItem=\"VVm-6p-iL2\" secondAttribute=\"leading\" constant=\"115\" id=\"Qu4-va-fMr\"/>\n                            <constraint firstItem=\"euP-3J-lWH\" firstAttribute=\"leading\" secondItem=\"VVm-6p-iL2\" secondAttribute=\"leading\" constant=\"115\" id=\"RS1-we-Q0K\"/>\n                            <constraint firstItem=\"PU4-Gc-gVh\" firstAttribute=\"firstBaseline\" secondItem=\"euP-3J-lWH\" secondAttribute=\"firstBaseline\" id=\"RZg-jH-DXx\"/>\n                            <constraint firstItem=\"SZR-32-kbI\" firstAttribute=\"firstBaseline\" secondItem=\"8nk-DS-uQp\" secondAttribute=\"firstBaseline\" id=\"aOe-Nw-CML\"/>\n                            <constraint firstItem=\"Zts-Q2-7Ll\" firstAttribute=\"leading\" secondItem=\"7bY-na-F0E\" secondAttribute=\"trailing\" constant=\"8\" id=\"jWd-kw-w63\"/>\n                            <constraint firstItem=\"euP-3J-lWH\" firstAttribute=\"top\" secondItem=\"7bY-na-F0E\" secondAttribute=\"bottom\" constant=\"15\" id=\"knT-8a-Uqf\"/>\n                            <constraint firstItem=\"7bY-na-F0E\" firstAttribute=\"top\" secondItem=\"K2l-e4-wXg\" secondAttribute=\"bottom\" constant=\"15\" id=\"qu0-gr-EfT\"/>\n                            <constraint firstItem=\"7bY-na-F0E\" firstAttribute=\"leading\" secondItem=\"SdT-xC-Llf\" secondAttribute=\"trailing\" constant=\"8\" id=\"unO-so-yK3\"/>\n                        </constraints>\n                    </view>\n                    <font key=\"titleFont\" metaFont=\"system\" size=\"14\"/>\n                </box>\n            </subviews>\n            <constraints>\n                <constraint firstItem=\"sZh-ot-4zc\" firstAttribute=\"top\" secondItem=\"qfZ-Cq-UaC\" secondAttribute=\"bottom\" constant=\"22\" id=\"2RU-WF-0K0\"/>\n                <constraint firstItem=\"qfZ-Cq-UaC\" firstAttribute=\"top\" secondItem=\"8QF-Al-Xli\" secondAttribute=\"bottom\" constant=\"22\" id=\"7Qd-uv-jhY\"/>\n                <constraint firstItem=\"qfZ-Cq-UaC\" firstAttribute=\"firstBaseline\" secondItem=\"Oei-up-hVB\" secondAttribute=\"firstBaseline\" id=\"8BG-Dk-YXM\"/>\n                <constraint firstItem=\"OK0-JG-81Q\" firstAttribute=\"top\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"top\" constant=\"16\" id=\"8j1-WM-uC5\"/>\n                <constraint firstItem=\"JFQ-iQ-S3H\" firstAttribute=\"top\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"top\" constant=\"10\" id=\"BdQ-FV-rlf\"/>\n                <constraint firstItem=\"PYx-68-4kx\" firstAttribute=\"leading\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"leading\" constant=\"168\" id=\"H3h-Eo-y9Y\"/>\n                <constraint firstItem=\"PYx-68-4kx\" firstAttribute=\"top\" secondItem=\"sZh-ot-4zc\" secondAttribute=\"bottom\" constant=\"22\" id=\"HMC-qG-5fJ\"/>\n                <constraint firstItem=\"8QF-Al-Xli\" firstAttribute=\"leading\" secondItem=\"cMW-Uc-M4F\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"K8w-9f-aB9\"/>\n                <constraint firstItem=\"n6K-Mt-UWg\" firstAttribute=\"top\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"top\" constant=\"54\" id=\"Nqf-pc-Dc7\"/>\n                <constraint firstItem=\"cMW-Uc-M4F\" firstAttribute=\"leading\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"leading\" constant=\"16\" id=\"Nsg-aZ-2f2\"/>\n                <constraint firstItem=\"qfZ-Cq-UaC\" firstAttribute=\"leading\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"leading\" constant=\"168\" id=\"OIO-9s-O63\"/>\n                <constraint firstItem=\"sZh-ot-4zc\" firstAttribute=\"firstBaseline\" secondItem=\"FYf-yB-Ksg\" secondAttribute=\"firstBaseline\" id=\"TLy-j6-BI5\"/>\n                <constraint firstItem=\"n6K-Mt-UWg\" firstAttribute=\"top\" secondItem=\"JFQ-iQ-S3H\" secondAttribute=\"bottom\" constant=\"10\" id=\"TvU-IF-eJZ\"/>\n                <constraint firstItem=\"sZh-ot-4zc\" firstAttribute=\"leading\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"leading\" constant=\"168\" id=\"UOp-TT-k3x\"/>\n                <constraint firstItem=\"8QF-Al-Xli\" firstAttribute=\"top\" secondItem=\"n6K-Mt-UWg\" secondAttribute=\"bottom\" constant=\"11\" id=\"XND-Qk-iBh\"/>\n                <constraint firstItem=\"sZh-ot-4zc\" firstAttribute=\"leading\" secondItem=\"FYf-yB-Ksg\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"bb4-6K-RXY\"/>\n                <constraint firstItem=\"PYx-68-4kx\" firstAttribute=\"leading\" secondItem=\"eyI-Yg-cqz\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"cA8-nN-2nj\"/>\n                <constraint firstItem=\"OK0-JG-81Q\" firstAttribute=\"leading\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"leading\" constant=\"54\" id=\"fCo-2b-1XE\"/>\n                <constraint firstItem=\"n6K-Mt-UWg\" firstAttribute=\"leading\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"leading\" constant=\"16\" id=\"hvL-pz-UwR\"/>\n                <constraint firstItem=\"JFQ-iQ-S3H\" firstAttribute=\"leading\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"leading\" constant=\"16\" id=\"iCq-Z3-8AD\"/>\n                <constraint firstItem=\"cMW-Uc-M4F\" firstAttribute=\"top\" secondItem=\"n6K-Mt-UWg\" secondAttribute=\"bottom\" constant=\"9\" id=\"j8J-iO-rJv\"/>\n                <constraint firstItem=\"PYx-68-4kx\" firstAttribute=\"firstBaseline\" secondItem=\"eyI-Yg-cqz\" secondAttribute=\"firstBaseline\" id=\"kts-Cd-y9b\"/>\n                <constraint firstItem=\"qfZ-Cq-UaC\" firstAttribute=\"leading\" secondItem=\"Oei-up-hVB\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"qId-4L-Z3F\"/>\n                <constraint firstAttribute=\"trailing\" secondItem=\"n6K-Mt-UWg\" secondAttribute=\"trailing\" constant=\"16\" id=\"snR-zm-sMx\"/>\n                <constraint firstAttribute=\"width\" relation=\"greaterThanOrEqual\" constant=\"811\" id=\"uIY-ZA-90g\"/>\n                <constraint firstAttribute=\"height\" relation=\"greaterThanOrEqual\" constant=\"530\" id=\"wXF-CK-SGh\"/>\n            </constraints>\n            <point key=\"canvasLocation\" x=\"798.5\" y=\"284\"/>\n        </customView>\n        <window title=\"Edit margins manually\" allowsToolTipsWhenApplicationIsInactive=\"NO\" autorecalculatesKeyViewLoop=\"NO\" hidesOnDeactivate=\"YES\" releasedWhenClosed=\"NO\" visibleAtLaunch=\"NO\" frameAutosaveName=\"\" animationBehavior=\"default\" id=\"I9Z-Fv-GnD\" customClass=\"NSPanel\">\n            <windowStyleMask key=\"styleMask\" titled=\"YES\" closable=\"YES\" utility=\"YES\"/>\n            <windowPositionMask key=\"initialPositionMask\" leftStrut=\"YES\" rightStrut=\"YES\" topStrut=\"YES\" bottomStrut=\"YES\"/>\n            <rect key=\"contentRect\" x=\"272\" y=\"172\" width=\"590\" height=\"412\"/>\n            <rect key=\"screenRect\" x=\"0.0\" y=\"0.0\" width=\"2560\" height=\"1415\"/>\n            <view key=\"contentView\" id=\"b57-oU-iVB\">\n                <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"590\" height=\"412\"/>\n                <autoresizingMask key=\"autoresizingMask\"/>\n                <subviews>\n                    <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" fixedFrame=\"YES\" preferredMaxLayoutWidth=\"550\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"VsM-3A-xWb\">\n                        <rect key=\"frame\" x=\"18\" y=\"353\" width=\"554\" height=\"39\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" flexibleMinY=\"YES\"/>\n                        <textFieldCell key=\"cell\" title=\"Edit the vertical/horizontal offset that should be applied to each screen, relative to it's initial position. \" id=\"1Zv-75-eWG\">\n                            <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                            <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                            <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        </textFieldCell>\n                    </textField>\n                    <textField focusRingType=\"none\" verticalHuggingPriority=\"750\" horizontalCompressionResistancePriority=\"250\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Whr-Ke-RvG\">\n                        <rect key=\"frame\" x=\"20\" y=\"59\" width=\"550\" height=\"286\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <textFieldCell key=\"cell\" selectable=\"YES\" editable=\"YES\" sendsActionOnEndEditing=\"YES\" state=\"on\" borderStyle=\"bezel\" drawsBackground=\"YES\" id=\"8dw-qp-C44\">\n                            <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                            <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                            <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        </textFieldCell>\n                    </textField>\n                    <button verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"3GO-u2-6hd\">\n                        <rect key=\"frame\" x=\"436\" y=\"14\" width=\"137\" height=\"40\"/>\n                        <autoresizingMask key=\"autoresizingMask\" flexibleMinX=\"YES\" flexibleMaxY=\"YES\"/>\n                        <buttonCell key=\"cell\" type=\"push\" title=\"Apply and Close\" bezelStyle=\"rounded\" alignment=\"center\" controlSize=\"large\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"lLM-Gv-fgb\">\n                            <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                            <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        </buttonCell>\n                        <connections>\n                            <action selector=\"advancedModePanelApplyClose:\" target=\"-2\" id=\"5X4-c8-T00\"/>\n                        </connections>\n                    </button>\n                    <button verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"rfs-OT-GE7\">\n                        <rect key=\"frame\" x=\"306\" y=\"14\" width=\"128\" height=\"40\"/>\n                        <autoresizingMask key=\"autoresizingMask\" flexibleMinX=\"YES\" flexibleMaxY=\"YES\"/>\n                        <buttonCell key=\"cell\" type=\"push\" title=\"Apply changes\" bezelStyle=\"rounded\" alignment=\"center\" controlSize=\"large\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"LOd-4H-lDp\">\n                            <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                            <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        </buttonCell>\n                        <connections>\n                            <action selector=\"advancedModePanelApply:\" target=\"-2\" id=\"2oA-i0-S36\"/>\n                        </connections>\n                    </button>\n                </subviews>\n            </view>\n            <point key=\"canvasLocation\" x=\"894\" y=\"850\"/>\n        </window>\n    </objects>\n    <resources>\n        <image name=\"NSInfo\" width=\"32\" height=\"32\"/>\n        <image name=\"display.2\" catalog=\"system\" width=\"30\" height=\"20\"/>\n    </resources>\n</document>\n"
  },
  {
    "path": "Resources/MainUI/Settings panels/FiltersViewController.swift",
    "content": "//\n//  FiltersViewController.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 02/08/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Cocoa\nimport AVKit\n\nclass FiltersViewController: NSViewController {\n    @IBOutlet var imageView1: NSImageView!\n    @IBOutlet var imageView2: NSImageView!\n    @IBOutlet var imageView3: NSImageView!\n    @IBOutlet var imageView4: NSImageView!\n\n    @IBOutlet var vibranceSlider: NSSlider!\n\n    @IBOutlet var infoIcon: NSButton!\n    @IBOutlet var allowPerVideo: NSButton!\n    var images: [NSImageView: CIImage] = [:]\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n\n        vibranceSlider.doubleValue = PrefsVideos.globalVibrance\n\n        setupImages()\n        redrawFilteredImages()\n\n        infoIcon.setIcons(\"info.circle\")\n\n        allowPerVideo.state = PrefsVideos.allowPerVideoVibrance ? .on : .off\n    }\n\n    func setupImages() {\n        // Let's reset\n        images = [:]\n\n        // Get the cached currentRotation\n        let videos = VideoList.instance.currentRotation().filter({ $0.isAvailableOffline && !$0.isHDR() }).shuffled()\n\n        if !videos.isEmpty {\n            images[imageView1] = getImage(videos.first!)\n        }\n        if videos.count > 1 {\n            images[imageView2] = getImage(videos[1])\n        }\n        if videos.count > 2 {\n            images[imageView3] = getImage(videos[2])\n        }\n        if videos.count > 3 {\n            images[imageView4] = getImage(videos[3])\n        }\n\n    }\n\n    func redrawFilteredImages() {\n        for (view, image) in images {\n            setupImage(for: view, ciImage: image)\n        }\n    }\n\n    func getImage(_ video: AerialVideo) -> CIImage? {\n        if let url = Thumbnails.getLargeURL(forVideo: video) {\n            return CIImage(contentsOf: url)!\n        } else {\n            return nil\n        }\n    }\n\n    func setupImage(for imageView: NSImageView, ciImage: CIImage) {\n        if #available(OSX 10.14, *) {\n            if let vibrantImage = CIFilter(name: \"CIVibrance\",\n                                           parameters: [kCIInputImageKey: ciImage, kCIInputAmountKey: PrefsVideos.globalVibrance] )?.outputImage {\n                let rep = NSCIImageRep(ciImage: vibrantImage)\n                let nsImage = NSImage(size: rep.size)\n                nsImage.addRepresentation(rep)\n                imageView.image = nsImage\n            } else {\n                errorLog(\"Couldn't apply vibrance filter, please report\")\n            }\n        } else {\n            // Fallback on earlier versions\n            imageView.image = nil\n        }\n\n    }\n\n    @IBAction func vibranceSliderChange(_ sender: NSSlider) {\n        PrefsVideos.globalVibrance = sender.doubleValue\n        redrawFilteredImages()\n    }\n\n    @IBAction func allowPerVideoChange(_ sender: NSButton) {\n        PrefsVideos.allowPerVideoVibrance = sender.state == .on\n    }\n\n}\n"
  },
  {
    "path": "Resources/MainUI/Settings panels/FiltersViewController.xib",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.Cocoa.XIB\" version=\"3.0\" toolsVersion=\"22113.1\" targetRuntime=\"MacOSX.Cocoa\" propertyAccessControl=\"none\" useAutolayout=\"YES\" customObjectInstantitationMethod=\"direct\">\n    <dependencies>\n        <deployment identifier=\"macosx\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.CocoaPlugin\" version=\"22113.1\"/>\n        <capability name=\"Image references\" minToolsVersion=\"12.0\"/>\n        <capability name=\"System colors introduced in macOS 10.14\" minToolsVersion=\"10.0\"/>\n        <capability name=\"documents saved in the Xcode 8 format\" minToolsVersion=\"8.0\"/>\n    </dependencies>\n    <objects>\n        <customObject id=\"-2\" userLabel=\"File's Owner\" customClass=\"FiltersViewController\" customModule=\"Aerial\" customModuleProvider=\"target\">\n            <connections>\n                <outlet property=\"allowPerVideo\" destination=\"iob-wn-Pqt\" id=\"6Ju-KF-swU\"/>\n                <outlet property=\"imageView1\" destination=\"7LV-8e-x1j\" id=\"zgu-CN-Hhr\"/>\n                <outlet property=\"imageView2\" destination=\"8AX-SO-qGe\" id=\"aZc-Wr-YkL\"/>\n                <outlet property=\"imageView3\" destination=\"oJZ-sY-UYv\" id=\"RoH-Mv-Tip\"/>\n                <outlet property=\"imageView4\" destination=\"AvL-Xc-gaf\" id=\"rwE-4P-bkU\"/>\n                <outlet property=\"infoIcon\" destination=\"NWx-XD-ael\" id=\"Vwt-gN-n0u\"/>\n                <outlet property=\"vibranceSlider\" destination=\"oaK-yX-Fb3\" id=\"OKF-IO-d22\"/>\n                <outlet property=\"view\" destination=\"Hz6-mo-xeY\" id=\"0bl-1N-x8E\"/>\n            </connections>\n        </customObject>\n        <customObject id=\"-1\" userLabel=\"First Responder\" customClass=\"FirstResponder\"/>\n        <customObject id=\"-3\" userLabel=\"Application\" customClass=\"NSObject\"/>\n        <customView translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Hz6-mo-xeY\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"811\" height=\"530\"/>\n            <subviews>\n                <slider verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"oaK-yX-Fb3\">\n                    <rect key=\"frame\" x=\"238\" y=\"444\" width=\"264\" height=\"28\"/>\n                    <constraints>\n                        <constraint firstAttribute=\"width\" constant=\"260\" id=\"590-ll-J2f\"/>\n                    </constraints>\n                    <sliderCell key=\"cell\" controlSize=\"large\" continuous=\"YES\" state=\"on\" alignment=\"left\" minValue=\"-1\" maxValue=\"1\" tickMarkPosition=\"above\" numberOfTickMarks=\"3\" sliderType=\"linear\" id=\"bm8-i4-7iS\"/>\n                    <connections>\n                        <action selector=\"vibranceSliderChange:\" target=\"-2\" id=\"MTm-nT-NgR\"/>\n                    </connections>\n                </slider>\n                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"0GU-RH-zJp\">\n                    <rect key=\"frame\" x=\"86\" y=\"453\" width=\"148\" height=\"17\"/>\n                    <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" alignment=\"right\" title=\"Apply global vibrance:\" id=\"EXk-cA-wlS\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <customView translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Lkf-KS-VPB\">\n                    <rect key=\"frame\" x=\"60\" y=\"-9\" width=\"691\" height=\"389\"/>\n                    <subviews>\n                        <imageView horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" horizontalCompressionResistancePriority=\"75\" verticalCompressionResistancePriority=\"75\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"7LV-8e-x1j\">\n                            <rect key=\"frame\" x=\"0.0\" y=\"195\" width=\"346\" height=\"194\"/>\n                            <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" id=\"H9g-WZ-jAw\"/>\n                        </imageView>\n                        <imageView horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" horizontalCompressionResistancePriority=\"75\" verticalCompressionResistancePriority=\"75\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"8AX-SO-qGe\">\n                            <rect key=\"frame\" x=\"346\" y=\"195\" width=\"345\" height=\"194\"/>\n                            <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" id=\"KIl-bl-it3\"/>\n                        </imageView>\n                        <imageView horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" horizontalCompressionResistancePriority=\"75\" verticalCompressionResistancePriority=\"75\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"oJZ-sY-UYv\">\n                            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"346\" height=\"195\"/>\n                            <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" id=\"wAg-gs-Ch2\"/>\n                        </imageView>\n                        <imageView horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" horizontalCompressionResistancePriority=\"75\" verticalCompressionResistancePriority=\"75\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"AvL-Xc-gaf\">\n                            <rect key=\"frame\" x=\"346\" y=\"0.0\" width=\"345\" height=\"195\"/>\n                            <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" id=\"NNt-qy-ZNc\"/>\n                        </imageView>\n                    </subviews>\n                    <constraints>\n                        <constraint firstAttribute=\"centerX\" secondItem=\"7LV-8e-x1j\" secondAttribute=\"trailing\" id=\"5vZ-qE-uak\"/>\n                        <constraint firstItem=\"AvL-Xc-gaf\" firstAttribute=\"top\" secondItem=\"Lkf-KS-VPB\" secondAttribute=\"centerY\" id=\"8Ff-6Y-7XW\"/>\n                        <constraint firstAttribute=\"trailing\" secondItem=\"8AX-SO-qGe\" secondAttribute=\"trailing\" id=\"BZ5-Dm-01Q\"/>\n                        <constraint firstItem=\"AvL-Xc-gaf\" firstAttribute=\"leading\" secondItem=\"Lkf-KS-VPB\" secondAttribute=\"centerX\" id=\"CLR-zn-OZN\"/>\n                        <constraint firstItem=\"7LV-8e-x1j\" firstAttribute=\"leading\" secondItem=\"Lkf-KS-VPB\" secondAttribute=\"leading\" id=\"EK9-SX-yPM\"/>\n                        <constraint firstItem=\"8AX-SO-qGe\" firstAttribute=\"leading\" secondItem=\"Lkf-KS-VPB\" secondAttribute=\"centerX\" id=\"FDP-sY-Hel\"/>\n                        <constraint firstItem=\"oJZ-sY-UYv\" firstAttribute=\"top\" secondItem=\"Lkf-KS-VPB\" secondAttribute=\"centerY\" id=\"Lgj-rm-fzx\"/>\n                        <constraint firstAttribute=\"centerY\" secondItem=\"7LV-8e-x1j\" secondAttribute=\"bottom\" id=\"Mw0-ho-cQ2\"/>\n                        <constraint firstAttribute=\"centerX\" secondItem=\"oJZ-sY-UYv\" secondAttribute=\"trailing\" id=\"MzR-JW-qaQ\"/>\n                        <constraint firstAttribute=\"centerY\" secondItem=\"8AX-SO-qGe\" secondAttribute=\"bottom\" id=\"XA7-1d-YGn\"/>\n                        <constraint firstAttribute=\"bottom\" secondItem=\"oJZ-sY-UYv\" secondAttribute=\"bottom\" id=\"a6G-B1-Emd\"/>\n                        <constraint firstItem=\"8AX-SO-qGe\" firstAttribute=\"top\" secondItem=\"Lkf-KS-VPB\" secondAttribute=\"top\" id=\"cFp-Xo-Llk\"/>\n                        <constraint firstItem=\"7LV-8e-x1j\" firstAttribute=\"top\" secondItem=\"Lkf-KS-VPB\" secondAttribute=\"top\" id=\"cbc-i1-Ac8\"/>\n                        <constraint firstAttribute=\"trailing\" secondItem=\"AvL-Xc-gaf\" secondAttribute=\"trailing\" id=\"dLG-vS-XQP\"/>\n                        <constraint firstAttribute=\"width\" secondItem=\"Lkf-KS-VPB\" secondAttribute=\"height\" multiplier=\"16:9\" id=\"djB-ab-xGq\"/>\n                        <constraint firstItem=\"oJZ-sY-UYv\" firstAttribute=\"leading\" secondItem=\"Lkf-KS-VPB\" secondAttribute=\"leading\" id=\"gok-QH-Fv3\"/>\n                        <constraint firstAttribute=\"bottom\" secondItem=\"AvL-Xc-gaf\" secondAttribute=\"bottom\" id=\"vzz-kL-8jN\"/>\n                    </constraints>\n                </customView>\n                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"JZe-5t-O4C\">\n                    <rect key=\"frame\" x=\"116\" y=\"413\" width=\"686\" height=\"17\"/>\n                    <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"Vibrance lets you adjust the colors of videos to make them pop more. This is not available for HDR videos.\" id=\"SB0-6z-9YD\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <button translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"NWx-XD-ael\">\n                    <rect key=\"frame\" x=\"86\" y=\"410\" width=\"24\" height=\"24\"/>\n                    <buttonCell key=\"cell\" type=\"square\" bezelStyle=\"shadowlessSquare\" image=\"info.circle\" imagePosition=\"only\" alignment=\"center\" imageScaling=\"proportionallyUpOrDown\" inset=\"2\" id=\"qrp-00-xdz\">\n                        <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\"/>\n                    </buttonCell>\n                    <constraints>\n                        <constraint firstAttribute=\"height\" constant=\"24\" id=\"DfM-Cy-mvh\"/>\n                        <constraint firstAttribute=\"width\" constant=\"24\" id=\"qKd-mm-nDx\"/>\n                    </constraints>\n                </button>\n                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"7rn-od-imW\">\n                    <rect key=\"frame\" x=\"52\" y=\"497\" width=\"363\" height=\"17\"/>\n                    <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"Select which information should be overlayed on videos\" id=\"kZK-qe-87B\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <imageView horizontalHuggingPriority=\"25\" verticalHuggingPriority=\"25\" horizontalCompressionResistancePriority=\"75\" verticalCompressionResistancePriority=\"75\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"gp8-EJ-ObO\">\n                    <rect key=\"frame\" x=\"16\" y=\"482\" width=\"28.5\" height=\"42\"/>\n                    <constraints>\n                        <constraint firstAttribute=\"width\" constant=\"28\" id=\"Iky-aW-ddG\"/>\n                        <constraint firstAttribute=\"height\" constant=\"34\" id=\"T7k-tP-81o\"/>\n                    </constraints>\n                    <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyUpOrDown\" id=\"f3x-mP-8c0\">\n                        <imageReference key=\"image\" image=\"slider.horizontal.3\" catalog=\"system\" symbolScale=\"large\"/>\n                    </imageCell>\n                    <color key=\"contentTintColor\" name=\"controlAccentColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                </imageView>\n                <button verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"iob-wn-Pqt\">\n                    <rect key=\"frame\" x=\"513\" y=\"452.5\" width=\"185\" height=\"18\"/>\n                    <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                    <buttonCell key=\"cell\" type=\"check\" title=\"Allow per video vibrance\" bezelStyle=\"regularSquare\" imagePosition=\"left\" inset=\"2\" id=\"CxY-Zt-3Oi\">\n                        <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"allowPerVideoChange:\" target=\"-2\" id=\"dbZ-6n-ct2\"/>\n                    </connections>\n                </button>\n            </subviews>\n            <constraints>\n                <constraint firstItem=\"gp8-EJ-ObO\" firstAttribute=\"top\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"top\" constant=\"10\" id=\"2Wi-0g-Dod\"/>\n                <constraint firstItem=\"JZe-5t-O4C\" firstAttribute=\"centerY\" secondItem=\"NWx-XD-ael\" secondAttribute=\"centerY\" id=\"2gk-tU-yp0\"/>\n                <constraint firstItem=\"gp8-EJ-ObO\" firstAttribute=\"leading\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"leading\" constant=\"16\" id=\"6gz-Aq-vNN\"/>\n                <constraint firstItem=\"JZe-5t-O4C\" firstAttribute=\"leading\" secondItem=\"NWx-XD-ael\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"8Hn-KI-4jF\"/>\n                <constraint firstItem=\"Lkf-KS-VPB\" firstAttribute=\"top\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"top\" constant=\"150\" id=\"9iW-YK-N19\"/>\n                <constraint firstItem=\"NWx-XD-ael\" firstAttribute=\"leading\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"leading\" constant=\"86\" id=\"Egc-rM-AaO\"/>\n                <constraint firstItem=\"oaK-yX-Fb3\" firstAttribute=\"leading\" secondItem=\"0GU-RH-zJp\" secondAttribute=\"trailing\" constant=\"8\" id=\"GCR-JE-7tQ\"/>\n                <constraint firstItem=\"Lkf-KS-VPB\" firstAttribute=\"leading\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"leading\" constant=\"60\" id=\"MFl-gR-4Cv\"/>\n                <constraint firstItem=\"7rn-od-imW\" firstAttribute=\"top\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"top\" constant=\"16\" id=\"UdV-Sj-pRV\"/>\n                <constraint firstItem=\"oaK-yX-Fb3\" firstAttribute=\"top\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"top\" constant=\"60\" id=\"WVf-Pi-IAW\"/>\n                <constraint firstAttribute=\"height\" relation=\"greaterThanOrEqual\" constant=\"530\" id=\"Xgc-7b-f5x\"/>\n                <constraint firstAttribute=\"width\" relation=\"greaterThanOrEqual\" constant=\"811\" id=\"ZZJ-S9-wPb\"/>\n                <constraint firstItem=\"oaK-yX-Fb3\" firstAttribute=\"leading\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"leading\" constant=\"240\" id=\"bIs-qY-CO3\"/>\n                <constraint firstAttribute=\"trailing\" secondItem=\"Lkf-KS-VPB\" secondAttribute=\"trailing\" constant=\"60\" id=\"dux-Td-5U0\"/>\n                <constraint firstItem=\"JZe-5t-O4C\" firstAttribute=\"top\" secondItem=\"oaK-yX-Fb3\" secondAttribute=\"bottom\" constant=\"20\" id=\"hFr-sk-O7a\"/>\n                <constraint firstItem=\"0GU-RH-zJp\" firstAttribute=\"top\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"top\" constant=\"60\" id=\"sju-ce-g1L\"/>\n                <constraint firstItem=\"7rn-od-imW\" firstAttribute=\"leading\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"leading\" constant=\"54\" id=\"yFq-WC-sEf\"/>\n            </constraints>\n            <point key=\"canvasLocation\" x=\"-1591\" y=\"296.5\"/>\n        </customView>\n    </objects>\n    <resources>\n        <image name=\"info.circle\" width=\"141\" height=\"155\"/>\n        <image name=\"slider.horizontal.3\" catalog=\"system\" width=\"21\" height=\"17\"/>\n    </resources>\n</document>\n"
  },
  {
    "path": "Resources/MainUI/Settings panels/NowPlayingViewController.swift",
    "content": "//\n//  NowPlayingViewController.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 18/11/2021.\n//  Copyright © 2021 Guillaume Louel. All rights reserved.\n//\n\nimport Cocoa\n\nclass NowPlayingViewController: NSViewController {\n\n    // Top toolbar\n    @IBOutlet var playIconImageView: NSImageView!\n\n    @IBOutlet var currentlySelectedPopupButton: NSPopUpButton!\n\n    @IBOutlet var selectAllButton: NSButton!\n    @IBOutlet var deselectAllButton: NSButton!\n\n    // Our main collection\n    @IBOutlet var playingCollectionView: NowPlayingCollectionView!\n\n    // Status stuff\n    @IBOutlet var statusDriveImageView: NSImageView!\n    @IBOutlet var statusDriveLabel: NSTextField!\n\n    @IBOutlet var statusTimeImageView: NSImageView!\n    @IBOutlet var statusTimeLabel: NSTextField!\n\n    @IBOutlet weak var statusHiddenVideoButton: NSButton!\n\n    @IBOutlet weak var statusFavoriteButton: NSButton!\n    \n    var sources: [String] = []\n    var currentSource: VideoList.FilterMode = .location\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n\n        // This is the filter we use to populate the view\n        updateCurrentSource()\n\n        // Reflect on UI\n        currentlySelectedPopupButton.selectItem(at: PrefsVideos.intNewShouldPlay)\n\n\n\n        // Now update the UI\n        reloadSources()\n        updateStatusBar()\n\n        // Setup collection\n        playingCollectionView.dataSource = self\n        playingCollectionView.wantsLayer = true\n\n\n        \n        VideoList.instance.addCallback {\n            debugLog(\"NPrs\")\n            self.reloadSources()\n            self.updateStatusBar()\n            \n            if self.isSelectionEmpty() {\n                self.selectAllClick(self.selectAllButton!)\n            }\n        }\n    }\n\n    // This is our filter on this panel\n    func updateCurrentSource() {\n        switch PrefsVideos.newShouldPlay {\n        case .location:\n            currentSource = .location\n        case .favorites:\n            currentSource = .favorite\n        case .time:\n            currentSource = .time\n        case .scene:\n            currentSource = .scene\n        case .source:\n            currentSource = .source\n        }\n    }\n\n    @IBAction func currentlySelectedChange(_ sender: NSPopUpButton) {\n        PrefsVideos.newShouldPlay = NewShouldPlay(rawValue: sender.indexOfSelectedItem)!\n\n        updateCurrentSource()\n        reloadSources()\n        updateStatusBar()\n        \n        if self.isSelectionEmpty() {\n            self.selectAllClick(self.selectAllButton!)\n        }\n    }\n\n    func isSelectionEmpty() -> Bool {\n        let subSources = VideoList.instance.getSources(mode: currentSource)\n\n        let mode = String(describing: currentSource) + \":\"\n\n        for source in subSources {\n            let path = mode + source\n            if PrefsVideos.newShouldPlayString.contains(path) {\n                return false\n            }\n        }\n        \n        return true\n    }\n    \n    \n    @IBAction func selectAllClick(_ sender: Any) {\n        let subSources = VideoList.instance.getSources(mode: currentSource)\n\n        let mode = String(describing: currentSource) + \":\"\n\n        for source in subSources {\n            let path = mode + source\n\n            if !PrefsVideos.newShouldPlayString.contains(path) {\n                PrefsVideos.newShouldPlayString.append(path)\n            }\n        }\n        playingCollectionView.reloadData()\n    }\n\n    @IBAction func statusHiddenVideoButtonClick(_ sender: Any) {\n        Aerial.helper.windowController?.browseTo(\"hidden:0\")\n    }\n   \n    @IBAction func statusFavoritesButtonClick(_ sender: Any) {\n        Aerial.helper.windowController?.browseTo(\"favorites:0\")\n    }\n    \n    @IBAction func deselectAllClick(_ sender: Any) {\n        let subSources = VideoList.instance.getSources(mode: currentSource)\n\n        let mode = String(describing: currentSource) + \":\"\n\n        for source in subSources {\n            let path = mode + source\n            if PrefsVideos.newShouldPlayString.contains(path) {\n                PrefsVideos.newShouldPlayString.remove(at: PrefsVideos.newShouldPlayString.firstIndex(of: path)!)\n            }\n        }\n        playingCollectionView.reloadData()\n    }\n\n    public func reloadSources() {\n        sources = VideoList.instance.getSources(mode: currentSource)\n        playingCollectionView.reloadData()\n    }\n\n    func updateStatusBar() {\n        if PrefsCache.enableManagement {\n            // We are in managed mode\n            if PrefsCache.cacheLimit >= 101 {\n                statusDriveImageView.image = Aerial.helper.getAccentedSymbol(\"externaldrive.badge.checkmark\")\n                statusDriveLabel.stringValue = String(Cache.size().rounded(toPlaces: 1)) + \" GB\"\n            } else if Cache.isFull() {\n                statusDriveImageView.image = Aerial.helper.getAccentedSymbol(\"externaldrive.badge.xmark\")\n                statusDriveLabel.stringValue = Cache.sizeString() + \" (your cache is full)\"\n            } else {\n                statusDriveImageView.image = Aerial.helper.getAccentedSymbol(\"externaldrive.badge.checkmark\")\n                statusDriveLabel.stringValue = String(Cache.size().rounded(toPlaces: 1)) + \" / \" + String(PrefsCache.cacheLimit.rounded(toPlaces: 1)) + \" GB\"\n            }\n        } else {\n            // Manual mode\n            statusDriveImageView.image = Aerial.helper.getAccentedSymbol(\"internaldrive\")\n            statusDriveLabel.stringValue = Cache.sizeString()\n        }\n\n        // May get removed\n        statusTimeImageView.isHidden = true\n        statusTimeLabel.isHidden = true\n        \n        if PrefsVideos.hidden.isEmpty {\n            statusHiddenVideoButton.title = \"No hidden videos\"\n        } else if PrefsVideos.hidden.count == 1 {\n            statusHiddenVideoButton.title = String(PrefsVideos.hidden.count) + \" hidden video\"\n        } else {\n            statusHiddenVideoButton.title = String(PrefsVideos.hidden.count) + \" hidden videos\"\n        }\n        \n        if (PrefsVideos.favorites.isEmpty) {\n            statusFavoriteButton.title = \"No favorites\"\n        } else if PrefsVideos.favorites.count == 1 {\n            statusFavoriteButton.title = String(PrefsVideos.favorites.count) + \" favorite\"\n        } else {\n            statusFavoriteButton.title = String(PrefsVideos.favorites.count) + \" favorites\"\n        }\n    }\n\n}\n\nextension NowPlayingViewController: NSCollectionViewDataSource {\n\n    func numberOfSections(in collectionView: NSCollectionView) -> Int {\n        return 1\n    }\n\n    func collectionView(_ collectionView: NSCollectionView, numberOfItemsInSection section: Int) -> Int {\n        return sources.count\n    }\n\n    func collectionView(_ itemForRepresentedObjectAtcollectionView: NSCollectionView,\n                        itemForRepresentedObjectAt indexPath: IndexPath) -> NSCollectionViewItem {\n\n        let item = playingCollectionView.makeItem(withIdentifier:\n                        NSUserInterfaceItemIdentifier(rawValue: \"PlayingCollectionViewItem\"), for: indexPath)\n\n        guard let playingCollectionViewItem = item as? PlayingCollectionViewItem else {return item}\n\n        playingCollectionViewItem.nowPlayingViewController = self\n        \n        let path = String(describing: currentSource) + \":\" + sources[indexPath[1]]\n        playingCollectionViewItem.hiddenPath.stringValue = path\n\n        playingCollectionViewItem.numberedPath.stringValue = String(describing: currentSource) + \":\" + String(indexPath[1])\n        \n        if PrefsVideos.newShouldPlayString.contains(path) {\n            playingCollectionViewItem.checkImageButton?.state = .on\n            playingCollectionViewItem.checkImageButton?.image = Aerial.helper.getSymbol(\"checkmark.circle.fill\")\n        } else {\n            playingCollectionViewItem.checkImageButton?.state = .off\n            playingCollectionViewItem.checkImageButton?.image = Aerial.helper.getSymbol(\"circle\")\n        }\n\n        playingCollectionViewItem.textField?.stringValue = sources[indexPath[1]]\n\n        let count = VideoList.instance.getVideosCountForSource(indexPath[1], mode: currentSource)\n\n        if count == 1 {\n            playingCollectionViewItem.extraTextField.stringValue =  \"\\(count) video\"\n        } else {\n            playingCollectionViewItem.extraTextField.stringValue =  \"\\(count) videos\"\n        }\n\n        let video = VideoList.instance.getVideosForSource(indexPath[1], mode: currentSource).first\n\n        if let video = video {\n            Thumbnails.get(forVideo: video) { [weak self] (img) in\n                guard let _ = self else { return }\n                if let img = img {\n                    playingCollectionViewItem.mainImageButton?.image = img\n                } else {\n                    playingCollectionViewItem.mainImageButton?.image = nil\n                }\n            }\n        }\n\n        return item\n    }\n\n}\n"
  },
  {
    "path": "Resources/MainUI/Settings panels/NowPlayingViewController.xib",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.Cocoa.XIB\" version=\"3.0\" toolsVersion=\"22113.1\" targetRuntime=\"MacOSX.Cocoa\" propertyAccessControl=\"none\" useAutolayout=\"YES\" customObjectInstantitationMethod=\"direct\">\n    <dependencies>\n        <deployment identifier=\"macosx\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.CocoaPlugin\" version=\"22113.1\"/>\n        <capability name=\"Image references\" minToolsVersion=\"12.0\"/>\n        <capability name=\"System colors introduced in macOS 10.14\" minToolsVersion=\"10.0\"/>\n        <capability name=\"documents saved in the Xcode 8 format\" minToolsVersion=\"8.0\"/>\n    </dependencies>\n    <objects>\n        <customObject id=\"-2\" userLabel=\"File's Owner\" customClass=\"NowPlayingViewController\" customModule=\"Aerial\" customModuleProvider=\"target\">\n            <connections>\n                <outlet property=\"currentlySelectedPopupButton\" destination=\"TIi-EV-o7z\" id=\"PeB-rO-Lrl\"/>\n                <outlet property=\"deselectAllButton\" destination=\"KuS-N2-Fqz\" id=\"OEH-uw-IMf\"/>\n                <outlet property=\"playIconImageView\" destination=\"NZB-in-TBi\" id=\"cSe-ul-Bzl\"/>\n                <outlet property=\"playingCollectionView\" destination=\"a8I-YB-mVT\" id=\"PrV-0B-Lec\"/>\n                <outlet property=\"selectAllButton\" destination=\"6Kq-mf-i1S\" id=\"cUl-Ou-oik\"/>\n                <outlet property=\"statusDriveImageView\" destination=\"4dU-Sh-aQm\" id=\"Sgk-Jg-TyC\"/>\n                <outlet property=\"statusDriveLabel\" destination=\"yZG-Gx-USb\" id=\"Lfv-Hf-xge\"/>\n                <outlet property=\"statusFavoriteButton\" destination=\"rwz-X2-gXF\" id=\"DbQ-u7-l2q\"/>\n                <outlet property=\"statusHiddenVideoButton\" destination=\"4il-vd-2Jh\" id=\"8m5-1k-4J0\"/>\n                <outlet property=\"statusTimeImageView\" destination=\"bpX-3f-k1M\" id=\"ldx-NT-ihb\"/>\n                <outlet property=\"statusTimeLabel\" destination=\"6Mj-az-MFS\" id=\"WC5-pQ-d9j\"/>\n                <outlet property=\"view\" destination=\"Hz6-mo-xeY\" id=\"0bl-1N-x8E\"/>\n            </connections>\n        </customObject>\n        <customObject id=\"-1\" userLabel=\"First Responder\" customClass=\"FirstResponder\"/>\n        <customObject id=\"-3\" userLabel=\"Application\" customClass=\"NSObject\"/>\n        <customView translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Hz6-mo-xeY\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"813\" height=\"530\"/>\n            <subviews>\n                <box boxType=\"custom\" borderWidth=\"0.0\" title=\"Box\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"IHM-F7-zr4\">\n                    <rect key=\"frame\" x=\"0.0\" y=\"477\" width=\"813\" height=\"53\"/>\n                    <view key=\"contentView\" id=\"XKz-3o-YVR\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"813\" height=\"53\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <subviews>\n                            <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Xha-Gi-SGi\">\n                                <rect key=\"frame\" x=\"52\" y=\"20\" width=\"174\" height=\"17\"/>\n                                <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" title=\"Play videos from selected:\" id=\"VFZ-gN-tW0\">\n                                    <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                    <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                </textFieldCell>\n                            </textField>\n                            <imageView horizontalHuggingPriority=\"25\" verticalHuggingPriority=\"25\" horizontalCompressionResistancePriority=\"75\" verticalCompressionResistancePriority=\"75\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"NZB-in-TBi\">\n                                <rect key=\"frame\" x=\"16\" y=\"5\" width=\"28\" height=\"44\"/>\n                                <constraints>\n                                    <constraint firstAttribute=\"width\" constant=\"28\" id=\"RVq-88-iHe\"/>\n                                </constraints>\n                                <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyUpOrDown\" id=\"uUh-Ai-r9z\">\n                                    <imageReference key=\"image\" image=\"play.circle\" catalog=\"system\" symbolScale=\"large\"/>\n                                </imageCell>\n                                <color key=\"contentTintColor\" name=\"controlAccentColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                            </imageView>\n                            <popUpButton verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"TIi-EV-o7z\">\n                                <rect key=\"frame\" x=\"235\" y=\"7\" width=\"134\" height=\"40\"/>\n                                <popUpButtonCell key=\"cell\" type=\"push\" title=\"Locations\" bezelStyle=\"rounded\" alignment=\"left\" controlSize=\"large\" lineBreakMode=\"truncatingTail\" state=\"on\" borderStyle=\"borderAndBezel\" imageScaling=\"proportionallyDown\" inset=\"2\" selectedItem=\"TKS-hW-LUa\" id=\"52p-bV-ZiC\">\n                                    <behavior key=\"behavior\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                                    <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                    <menu key=\"menu\" id=\"y5o-Nn-kjo\">\n                                        <items>\n                                            <menuItem title=\"Locations\" state=\"on\" image=\"location\" catalog=\"system\" id=\"TKS-hW-LUa\">\n                                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            </menuItem>\n                                            <menuItem title=\"Favorites\" image=\"star\" catalog=\"system\" id=\"F0q-UQ-Zz1\"/>\n                                            <menuItem title=\"Times\" image=\"clock\" catalog=\"system\" id=\"Zj1-2d-yg1\">\n                                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            </menuItem>\n                                            <menuItem title=\"Scenes\" image=\"leaf\" catalog=\"system\" id=\"Aci-Ar-TTk\">\n                                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            </menuItem>\n                                            <menuItem title=\"Sources\" image=\"video.badge.plus\" catalog=\"system\" id=\"9fd-f9-HGL\">\n                                                <attributedString key=\"attributedTitle\"/>\n                                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            </menuItem>\n                                            <menuItem title=\"Set\" image=\"book\" catalog=\"system\" hidden=\"YES\" id=\"rnF-bE-MYS\">\n                                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            </menuItem>\n                                        </items>\n                                    </menu>\n                                </popUpButtonCell>\n                                <connections>\n                                    <action selector=\"currentlySelectedChange:\" target=\"-2\" id=\"9uj-di-fUO\"/>\n                                </connections>\n                            </popUpButton>\n                            <box verticalHuggingPriority=\"750\" boxType=\"separator\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"sXq-JD-J6g\">\n                                <rect key=\"frame\" x=\"0.0\" y=\"-2\" width=\"813\" height=\"5\"/>\n                                <constraints>\n                                    <constraint firstAttribute=\"height\" constant=\"1\" id=\"HwB-mj-KMq\"/>\n                                </constraints>\n                            </box>\n                            <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"6Kq-mf-i1S\">\n                                <rect key=\"frame\" x=\"564\" y=\"9\" width=\"105\" height=\"35\"/>\n                                <buttonCell key=\"cell\" type=\"bevel\" title=\"Select All\" bezelStyle=\"regularSquare\" image=\"checkmark.square\" catalog=\"system\" imagePosition=\"leading\" alignment=\"center\" controlSize=\"large\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"bD8-ch-EUh\">\n                                    <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                                    <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                </buttonCell>\n                                <color key=\"bezelColor\" name=\"controlAccentColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                <connections>\n                                    <action selector=\"selectAllClick:\" target=\"-2\" id=\"51Z-bi-Eyo\"/>\n                                </connections>\n                            </button>\n                            <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"KuS-N2-Fqz\">\n                                <rect key=\"frame\" x=\"679\" y=\"9\" width=\"121\" height=\"35\"/>\n                                <buttonCell key=\"cell\" type=\"bevel\" title=\"Deselect All\" bezelStyle=\"regularSquare\" image=\"square\" catalog=\"system\" imagePosition=\"leading\" alignment=\"center\" controlSize=\"large\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"Xhu-KK-daR\">\n                                    <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                                    <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                </buttonCell>\n                                <color key=\"bezelColor\" name=\"controlAccentColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                <connections>\n                                    <action selector=\"deselectAllClick:\" target=\"-2\" id=\"MPt-FY-cnw\"/>\n                                </connections>\n                            </button>\n                        </subviews>\n                        <constraints>\n                            <constraint firstItem=\"sXq-JD-J6g\" firstAttribute=\"top\" secondItem=\"KuS-N2-Fqz\" secondAttribute=\"bottom\" constant=\"12\" id=\"2So-KG-tPz\"/>\n                            <constraint firstAttribute=\"bottom\" secondItem=\"sXq-JD-J6g\" secondAttribute=\"bottom\" id=\"4WQ-bH-wM9\"/>\n                            <constraint firstItem=\"KuS-N2-Fqz\" firstAttribute=\"leading\" secondItem=\"6Kq-mf-i1S\" secondAttribute=\"trailing\" constant=\"16\" id=\"4mD-zV-kTG\"/>\n                            <constraint firstItem=\"Xha-Gi-SGi\" firstAttribute=\"leading\" secondItem=\"XKz-3o-YVR\" secondAttribute=\"leading\" constant=\"54\" id=\"CPd-j0-Fcp\"/>\n                            <constraint firstItem=\"6Kq-mf-i1S\" firstAttribute=\"leading\" relation=\"greaterThanOrEqual\" secondItem=\"TIi-EV-o7z\" secondAttribute=\"trailing\" constant=\"16\" id=\"EMw-3O-ZOP\"/>\n                            <constraint firstItem=\"KuS-N2-Fqz\" firstAttribute=\"top\" secondItem=\"XKz-3o-YVR\" secondAttribute=\"top\" constant=\"12\" id=\"Gu2-iS-Dvg\"/>\n                            <constraint firstItem=\"sXq-JD-J6g\" firstAttribute=\"top\" secondItem=\"TIi-EV-o7z\" secondAttribute=\"bottom\" constant=\"12\" id=\"Hmv-HN-sgO\"/>\n                            <constraint firstItem=\"TIi-EV-o7z\" firstAttribute=\"top\" secondItem=\"XKz-3o-YVR\" secondAttribute=\"top\" constant=\"12\" id=\"J1E-Oh-8qT\"/>\n                            <constraint firstItem=\"sXq-JD-J6g\" firstAttribute=\"leading\" secondItem=\"XKz-3o-YVR\" secondAttribute=\"leading\" id=\"NyD-ff-Q1M\"/>\n                            <constraint firstItem=\"sXq-JD-J6g\" firstAttribute=\"top\" secondItem=\"6Kq-mf-i1S\" secondAttribute=\"bottom\" constant=\"12\" id=\"W92-Rx-Gwd\"/>\n                            <constraint firstAttribute=\"trailing\" secondItem=\"sXq-JD-J6g\" secondAttribute=\"trailing\" id=\"Xpg-lD-pyg\"/>\n                            <constraint firstItem=\"6Kq-mf-i1S\" firstAttribute=\"top\" secondItem=\"XKz-3o-YVR\" secondAttribute=\"top\" constant=\"12\" id=\"YHf-oF-kx2\"/>\n                            <constraint firstItem=\"NZB-in-TBi\" firstAttribute=\"leading\" secondItem=\"XKz-3o-YVR\" secondAttribute=\"leading\" constant=\"16\" id=\"cWM-N3-6aN\"/>\n                            <constraint firstItem=\"NZB-in-TBi\" firstAttribute=\"top\" secondItem=\"XKz-3o-YVR\" secondAttribute=\"top\" constant=\"10\" id=\"lVk-zQ-RgT\"/>\n                            <constraint firstItem=\"TIi-EV-o7z\" firstAttribute=\"firstBaseline\" secondItem=\"Xha-Gi-SGi\" secondAttribute=\"firstBaseline\" id=\"qD5-Sr-QJO\"/>\n                            <constraint firstAttribute=\"bottom\" secondItem=\"NZB-in-TBi\" secondAttribute=\"bottom\" constant=\"10\" id=\"rRs-uQ-JEJ\"/>\n                            <constraint firstItem=\"TIi-EV-o7z\" firstAttribute=\"leading\" secondItem=\"Xha-Gi-SGi\" secondAttribute=\"trailing\" constant=\"16\" id=\"ydQ-i2-G64\"/>\n                            <constraint firstAttribute=\"trailing\" secondItem=\"KuS-N2-Fqz\" secondAttribute=\"trailing\" constant=\"16\" id=\"ypz-S5-nxI\"/>\n                        </constraints>\n                    </view>\n                    <constraints>\n                        <constraint firstAttribute=\"height\" constant=\"53\" id=\"f8K-MQ-ebv\"/>\n                    </constraints>\n                    <color key=\"borderColor\" white=\"0.0\" alpha=\"0.0\" colorSpace=\"custom\" customColorSpace=\"genericGamma22GrayColorSpace\"/>\n                </box>\n                <box boxType=\"custom\" borderType=\"line\" borderWidth=\"0.0\" title=\"Box\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"52T-Wt-jny\">\n                    <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"813\" height=\"28\"/>\n                    <view key=\"contentView\" id=\"cSt-0j-uPZ\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"813\" height=\"28\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <subviews>\n                            <box verticalHuggingPriority=\"750\" boxType=\"separator\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"4DP-TC-303\">\n                                <rect key=\"frame\" x=\"0.0\" y=\"25\" width=\"813\" height=\"5\"/>\n                                <constraints>\n                                    <constraint firstAttribute=\"height\" constant=\"1\" id=\"oRw-t5-WKO\"/>\n                                </constraints>\n                            </box>\n                            <imageView horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"4dU-Sh-aQm\">\n                                <rect key=\"frame\" x=\"8\" y=\"2\" width=\"20\" height=\"24\"/>\n                                <constraints>\n                                    <constraint firstAttribute=\"height\" constant=\"20\" id=\"CIJ-yX-1bP\"/>\n                                    <constraint firstAttribute=\"width\" constant=\"20\" id=\"h21-Xx-OkQ\"/>\n                                </constraints>\n                                <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" id=\"mdP-mP-b0f\">\n                                    <imageReference key=\"image\" image=\"internaldrive\" catalog=\"system\" symbolScale=\"medium\"/>\n                                </imageCell>\n                                <color key=\"contentTintColor\" name=\"controlAccentColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                            </imageView>\n                            <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"yZG-Gx-USb\">\n                                <rect key=\"frame\" x=\"32\" y=\"7\" width=\"49\" height=\"14\"/>\n                                <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"4.7/5 GB\" id=\"TeH-g5-9in\">\n                                    <font key=\"font\" metaFont=\"smallSystem\"/>\n                                    <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                </textFieldCell>\n                            </textField>\n                            <imageView horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"bpX-3f-k1M\">\n                                <rect key=\"frame\" x=\"87\" y=\"1\" width=\"20.5\" height=\"27\"/>\n                                <constraints>\n                                    <constraint firstAttribute=\"width\" constant=\"20\" id=\"7kx-iO-95B\"/>\n                                    <constraint firstAttribute=\"height\" constant=\"20\" id=\"z86-IR-fSO\"/>\n                                </constraints>\n                                <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" id=\"weG-aK-DRq\">\n                                    <imageReference key=\"image\" image=\"sunset\" catalog=\"system\" symbolScale=\"medium\"/>\n                                </imageCell>\n                                <color key=\"contentTintColor\" name=\"controlAccentColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                            </imageView>\n                            <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"6Mj-az-MFS\">\n                                <rect key=\"frame\" x=\"113\" y=\"7\" width=\"36\" height=\"14\"/>\n                                <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"17h24\" id=\"YOo-5X-wAX\">\n                                    <font key=\"font\" metaFont=\"smallSystem\"/>\n                                    <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                </textFieldCell>\n                            </textField>\n                            <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"4il-vd-2Jh\">\n                                <rect key=\"frame\" x=\"749\" y=\"5\" width=\"56\" height=\"18.5\"/>\n                                <buttonCell key=\"cell\" type=\"inline\" title=\"Button\" bezelStyle=\"inline\" imagePosition=\"leading\" alignment=\"center\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"9bt-bt-RbV\">\n                                    <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                                    <font key=\"font\" metaFont=\"smallSystem\"/>\n                                    <imageReference key=\"image\" image=\"eye.slash\" catalog=\"system\" symbolScale=\"default\" renderingMode=\"hierarchical\">\n                                        <hierarchicalColors>\n                                            <color name=\"controlAccentColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                            <color name=\"controlAccentColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                            <color name=\"controlAccentColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                        </hierarchicalColors>\n                                    </imageReference>\n                                </buttonCell>\n                                <connections>\n                                    <action selector=\"statusHiddenVideoButtonClick:\" target=\"-2\" id=\"lNL-Al-7ma\"/>\n                                </connections>\n                            </button>\n                            <button verticalHuggingPriority=\"750\" misplaced=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"rwz-X2-gXF\">\n                                <rect key=\"frame\" x=\"687\" y=\"6\" width=\"54\" height=\"18.5\"/>\n                                <buttonCell key=\"cell\" type=\"inline\" title=\"Button\" bezelStyle=\"inline\" imagePosition=\"left\" alignment=\"center\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"0W5-ID-Fbw\">\n                                    <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                                    <font key=\"font\" metaFont=\"smallSystem\"/>\n                                    <imageReference key=\"image\" image=\"star.fill\" catalog=\"system\" symbolScale=\"default\" renderingMode=\"hierarchical\">\n                                        <hierarchicalColors>\n                                            <color name=\"controlAccentColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                            <color name=\"controlAccentColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                            <color name=\"controlAccentColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                        </hierarchicalColors>\n                                    </imageReference>\n                                </buttonCell>\n                                <connections>\n                                    <action selector=\"statusFavoritesButtonClick:\" target=\"-2\" id=\"TU2-ul-Mgq\"/>\n                                </connections>\n                            </button>\n                        </subviews>\n                        <constraints>\n                            <constraint firstAttribute=\"trailing\" secondItem=\"4il-vd-2Jh\" secondAttribute=\"trailing\" constant=\"8\" id=\"0JF-tL-7lU\"/>\n                            <constraint firstAttribute=\"bottom\" secondItem=\"rwz-X2-gXF\" secondAttribute=\"bottom\" constant=\"5\" id=\"3M1-3u-HNK\"/>\n                            <constraint firstItem=\"yZG-Gx-USb\" firstAttribute=\"leading\" secondItem=\"4dU-Sh-aQm\" secondAttribute=\"trailing\" constant=\"6\" id=\"6dO-TX-Xnw\"/>\n                            <constraint firstItem=\"bpX-3f-k1M\" firstAttribute=\"leading\" secondItem=\"yZG-Gx-USb\" secondAttribute=\"trailing\" constant=\"8\" id=\"6fI-zN-lVz\"/>\n                            <constraint firstItem=\"4DP-TC-303\" firstAttribute=\"top\" secondItem=\"cSt-0j-uPZ\" secondAttribute=\"top\" id=\"6s4-5G-wC3\"/>\n                            <constraint firstItem=\"6Mj-az-MFS\" firstAttribute=\"centerY\" secondItem=\"cSt-0j-uPZ\" secondAttribute=\"centerY\" id=\"7bp-fS-Vu7\"/>\n                            <constraint firstItem=\"bpX-3f-k1M\" firstAttribute=\"centerY\" secondItem=\"cSt-0j-uPZ\" secondAttribute=\"centerY\" id=\"Avw-Xa-fBN\"/>\n                            <constraint firstItem=\"4DP-TC-303\" firstAttribute=\"leading\" secondItem=\"cSt-0j-uPZ\" secondAttribute=\"leading\" id=\"LGk-5X-J8x\"/>\n                            <constraint firstAttribute=\"bottom\" secondItem=\"4il-vd-2Jh\" secondAttribute=\"bottom\" constant=\"5\" id=\"Ooi-wy-jl2\"/>\n                            <constraint firstAttribute=\"trailing\" secondItem=\"4DP-TC-303\" secondAttribute=\"trailing\" id=\"Pa3-2q-4oE\"/>\n                            <constraint firstItem=\"4il-vd-2Jh\" firstAttribute=\"leading\" secondItem=\"rwz-X2-gXF\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"T1H-G2-bIo\"/>\n                            <constraint firstItem=\"yZG-Gx-USb\" firstAttribute=\"centerY\" secondItem=\"cSt-0j-uPZ\" secondAttribute=\"centerY\" id=\"UBK-a1-BOf\"/>\n                            <constraint firstItem=\"rwz-X2-gXF\" firstAttribute=\"top\" secondItem=\"4DP-TC-303\" secondAttribute=\"bottom\" constant=\"4\" id=\"Z9y-ac-Nyh\"/>\n                            <constraint firstItem=\"4dU-Sh-aQm\" firstAttribute=\"leading\" secondItem=\"cSt-0j-uPZ\" secondAttribute=\"leading\" constant=\"8\" id=\"gkT-PJ-qsw\"/>\n                            <constraint firstItem=\"4dU-Sh-aQm\" firstAttribute=\"centerY\" secondItem=\"cSt-0j-uPZ\" secondAttribute=\"centerY\" id=\"ndU-IA-igS\"/>\n                            <constraint firstItem=\"4il-vd-2Jh\" firstAttribute=\"top\" secondItem=\"4DP-TC-303\" secondAttribute=\"bottom\" constant=\"4\" id=\"q30-AO-9aV\"/>\n                            <constraint firstItem=\"6Mj-az-MFS\" firstAttribute=\"leading\" secondItem=\"bpX-3f-k1M\" secondAttribute=\"trailing\" constant=\"8\" id=\"rjl-TE-Pry\"/>\n                        </constraints>\n                    </view>\n                    <constraints>\n                        <constraint firstAttribute=\"height\" constant=\"28\" id=\"5pa-Bg-52i\"/>\n                    </constraints>\n                </box>\n                <scrollView wantsLayer=\"YES\" borderType=\"none\" autohidesScrollers=\"YES\" horizontalLineScroll=\"10\" horizontalPageScroll=\"10\" verticalLineScroll=\"10\" verticalPageScroll=\"10\" hasHorizontalScroller=\"NO\" usesPredominantAxisScrolling=\"NO\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"vb7-sF-TVC\">\n                    <rect key=\"frame\" x=\"0.0\" y=\"28\" width=\"813\" height=\"449\"/>\n                    <clipView key=\"contentView\" drawsBackground=\"NO\" id=\"jH8-m2-LRr\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"813\" height=\"449\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <subviews>\n                            <collectionView selectable=\"YES\" allowsMultipleSelection=\"YES\" id=\"a8I-YB-mVT\" customClass=\"NowPlayingCollectionView\" customModule=\"Aerial\" customModuleProvider=\"target\">\n                                <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"813\" height=\"449\"/>\n                                <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\"/>\n                                <collectionViewFlowLayout key=\"collectionViewLayout\" minimumInteritemSpacing=\"30\" minimumLineSpacing=\"10\" id=\"6f2-wF-zBT\">\n                                    <size key=\"itemSize\" width=\"192\" height=\"149\"/>\n                                    <edgeInsets key=\"sectionInset\" left=\"30\" right=\"30\" top=\"30\" bottom=\"30\"/>\n                                </collectionViewFlowLayout>\n                                <color key=\"primaryBackgroundColor\" white=\"0.0\" alpha=\"0.0\" colorSpace=\"custom\" customColorSpace=\"genericGamma22GrayColorSpace\"/>\n                            </collectionView>\n                        </subviews>\n                        <color key=\"backgroundColor\" white=\"0.0\" alpha=\"0.0\" colorSpace=\"custom\" customColorSpace=\"genericGamma22GrayColorSpace\"/>\n                    </clipView>\n                    <scroller key=\"horizontalScroller\" hidden=\"YES\" wantsLayer=\"YES\" verticalHuggingPriority=\"750\" horizontal=\"YES\" id=\"wv2-Mo-D15\">\n                        <rect key=\"frame\" x=\"-100\" y=\"-100\" width=\"233\" height=\"15\"/>\n                        <autoresizingMask key=\"autoresizingMask\"/>\n                    </scroller>\n                    <scroller key=\"verticalScroller\" hidden=\"YES\" wantsLayer=\"YES\" verticalHuggingPriority=\"750\" doubleValue=\"1\" horizontal=\"NO\" id=\"lQ5-ou-esO\">\n                        <rect key=\"frame\" x=\"797\" y=\"0.0\" width=\"16\" height=\"368\"/>\n                        <autoresizingMask key=\"autoresizingMask\"/>\n                    </scroller>\n                </scrollView>\n            </subviews>\n            <constraints>\n                <constraint firstAttribute=\"width\" relation=\"greaterThanOrEqual\" constant=\"811\" id=\"2Se-bJ-T8d\"/>\n                <constraint firstItem=\"vb7-sF-TVC\" firstAttribute=\"leading\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"leading\" id=\"7PC-FR-Je6\"/>\n                <constraint firstAttribute=\"trailing\" secondItem=\"52T-Wt-jny\" secondAttribute=\"trailing\" id=\"9ur-Ty-2ev\"/>\n                <constraint firstItem=\"IHM-F7-zr4\" firstAttribute=\"top\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"top\" id=\"E0C-eb-Lh7\"/>\n                <constraint firstAttribute=\"bottom\" secondItem=\"52T-Wt-jny\" secondAttribute=\"bottom\" id=\"EyP-BV-a7g\"/>\n                <constraint firstAttribute=\"trailing\" secondItem=\"vb7-sF-TVC\" secondAttribute=\"trailing\" id=\"G21-Dz-HOf\"/>\n                <constraint firstAttribute=\"trailing\" secondItem=\"IHM-F7-zr4\" secondAttribute=\"trailing\" id=\"H02-Wy-bHk\"/>\n                <constraint firstItem=\"IHM-F7-zr4\" firstAttribute=\"leading\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"leading\" id=\"Jsc-0n-uHI\"/>\n                <constraint firstItem=\"vb7-sF-TVC\" firstAttribute=\"top\" secondItem=\"IHM-F7-zr4\" secondAttribute=\"bottom\" id=\"M32-MY-0FX\"/>\n                <constraint firstItem=\"52T-Wt-jny\" firstAttribute=\"top\" secondItem=\"vb7-sF-TVC\" secondAttribute=\"bottom\" id=\"edY-Od-c2Z\"/>\n                <constraint firstAttribute=\"height\" relation=\"greaterThanOrEqual\" constant=\"530\" id=\"njX-74-hPd\"/>\n                <constraint firstItem=\"52T-Wt-jny\" firstAttribute=\"leading\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"leading\" id=\"r8z-IZ-lcg\"/>\n            </constraints>\n            <point key=\"canvasLocation\" x=\"267.5\" y=\"253.5\"/>\n        </customView>\n        <menu id=\"yz3-GS-bRl\">\n            <items>\n                <menuItem title=\"Item 1\" id=\"OtB-eq-bC3\">\n                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                </menuItem>\n                <menuItem title=\"Item 2\" id=\"ssN-n4-AZ6\">\n                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                </menuItem>\n                <menuItem title=\"Item 3\" id=\"Eh5-xn-b2x\">\n                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                </menuItem>\n            </items>\n            <point key=\"canvasLocation\" x=\"-284\" y=\"728\"/>\n        </menu>\n    </objects>\n    <resources>\n        <image name=\"book\" catalog=\"system\" width=\"18\" height=\"14\"/>\n        <image name=\"checkmark.square\" catalog=\"system\" width=\"15\" height=\"14\"/>\n        <image name=\"clock\" catalog=\"system\" width=\"15\" height=\"15\"/>\n        <image name=\"eye.slash\" catalog=\"system\" width=\"21\" height=\"16\"/>\n        <image name=\"internaldrive\" catalog=\"system\" width=\"18\" height=\"13\"/>\n        <image name=\"leaf\" catalog=\"system\" width=\"16\" height=\"14\"/>\n        <image name=\"location\" catalog=\"system\" width=\"15\" height=\"15\"/>\n        <image name=\"play.circle\" catalog=\"system\" width=\"20\" height=\"20\"/>\n        <image name=\"square\" catalog=\"system\" width=\"15\" height=\"14\"/>\n        <image name=\"star\" catalog=\"system\" width=\"17\" height=\"16\"/>\n        <image name=\"star.fill\" catalog=\"system\" width=\"17\" height=\"16\"/>\n        <image name=\"sunset\" catalog=\"system\" width=\"20\" height=\"16\"/>\n        <image name=\"video.badge.plus\" catalog=\"system\" width=\"21\" height=\"16\"/>\n    </resources>\n</document>\n"
  },
  {
    "path": "Resources/MainUI/Settings panels/OverlaysViewController.swift",
    "content": "//\n//  OverlaysViewController.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 19/07/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Cocoa\n\nclass OverlaysViewController: NSViewController {\n    @IBOutlet var popoverWeather: NSPopover!\n    @IBOutlet var infoTableView: NSTableView!\n    @IBOutlet var infoSettingsTableView: NSTableView!\n    //@IBOutlet var infoBox: NSBox!\n    //@IBOutlet var infoContainerView: InfoContainerView!\n\n    @IBOutlet weak var hideUnderCompanion: NSButton!\n    \n    @IBOutlet var infoScrollView: NSScrollView!\n    @IBOutlet var infoScrollableView: InfoContainerView!\n    \n    // Then all the individual views\n    @IBOutlet var infoSettingsView: InfoSettingsView!\n    @IBOutlet var infoCommonView: InfoCommonView!\n\n    @IBOutlet var infoLocationView: InfoLocationView!\n    @IBOutlet var infoClockView: InfoClockView!\n    @IBOutlet var infoMessageView: InfoMessageView!\n\n    // Message sub panels\n    @IBOutlet var infoMessageTextView: NSView!\n    @IBOutlet var infoMessageShellView: NSView!\n    @IBOutlet var infoMessageTextFileView: NSView!\n\n    @IBOutlet var infoBatteryView: InfoBatteryView!\n    @IBOutlet var infoCountdownView: InfoCountdownView!\n    @IBOutlet var infoTimerView: InfoTimerView!\n    @IBOutlet var infoDateView: InfoDateView!\n    @IBOutlet var infoWeatherView: InfoWeatherView!\n\n    @IBOutlet var infoMusicView: InfoMusicView!\n    @IBOutlet var fontButton: NSButton!\n    @IBOutlet var trashButton: NSButton!\n\n    // And our weather panel\n    @IBOutlet var weatherPanel: NSPanel!\n    @IBOutlet var weatherCustomView: NSView!\n    @IBOutlet var weatherLabel: NSTextField!\n\n    var infoSource = InfoTableSource()\n    var infoSettingsSource = InfoSettingsTableSource()\n\n    var currentSubMessage: NSView?\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n        PrefsInfo.updateLayerList()\n\n        // Do view setup here.\n        fontButton.setIcons(\"textformat.alt\")\n        trashButton.setIcons(\"trash\")\n        infoSource.setController(self)\n        infoTableView.dataSource = infoSource\n        infoTableView.delegate = infoSource\n        infoTableView.registerForDraggedTypes([NSPasteboard.PasteboardType(rawValue: \"private.table-row\")])\n\n        infoSettingsSource.setController(self)\n        infoSettingsTableView.dataSource = infoSettingsSource\n        infoSettingsTableView.delegate = infoSettingsSource\n\n        hideUnderCompanion.state = PrefsInfo.hideUnderCompanion ? .on : .off\n        \n        // Calling this in both viewDidLoad and viewDidAppear prevents a vertical shift\n        drawInfoPanel(forType: PrefsInfo.layers[infoTableView.selectedRow])\n    }\n\n    override func viewDidAppear() {\n        drawInfoPanel(forType: PrefsInfo.layers[infoTableView.selectedRow])\n    }\n    \n    @IBAction func hideUnderCompanionClick(_ sender: NSButton) {\n        PrefsInfo.hideUnderCompanion = sender.state == .on\n    }\n    \n    func drawInfoSettingsPanel() {\n        resetInfoPanel()\n\n        // Add the common block of features (enabled, font, position, screen)\n        infoScrollableView.addSubview(infoSettingsView)\n\n        //infoContainerView.addSubview(infoSettingsView)\n        //infoBox.title = \"Advanced text settings\"\n        infoSettingsView.setStates()\n    }\n\n    // We dynamically change the content here, based on what's selected\n    func drawInfoPanel(forType: InfoType) {\n        resetInfoPanel()\n\n        // Add the common block of features (enabled, font, position, screen)\n        infoScrollableView.addSubview(infoCommonView)\n        //infoContainerView.addSubview(infoCommonView)\n        infoCommonView.setType(forType, controller: self)\n        infoScrollableView.setFrameSize(NSSize(width: infoScrollableView.frame.width, height: 800))\n\n        infoCommonView.frame.origin.y = 0\n\n        //infoScrollView.documentView?.scroll(.zero)\n\n        \n        // Then the per-type blocks if any\n        switch forType {\n        case .location:\n            infoScrollableView.addSubview(infoLocationView)\n            infoLocationView.frame.origin.y = infoCommonView.frame.height\n            infoLocationView.setStates()\n            \n            //infoScrollableView.setFrameSize(NSSize(width: infoScrollableView.frame.width, height: infoCommonView.frame.height + infoLocationView.frame.height))\n        case .message:\n            infoScrollableView.addSubview(infoMessageView)\n            infoMessageView.frame.origin.y = infoCommonView.frame.height\n            addSubMessagePanel()\n            infoMessageView.setStates()\n            //infoScrollableView.setFrameSize(NSSize(width: infoScrollableView.frame.width, height: infoCommonView.frame.height + infoLocationView.frame.height))\n        case .clock:\n            infoScrollableView.addSubview(infoClockView)\n            infoClockView.frame.origin.y = infoCommonView.frame.height\n            infoClockView.setStates()\n            //infoScrollableView.setFrameSize(NSSize(width: infoScrollableView.frame.width, height: infoCommonView.frame.height + infoClockView.frame.height))\n        case .date:\n            infoScrollableView.addSubview(infoDateView)\n            infoDateView.frame.origin.y = infoCommonView.frame.height\n            infoDateView.setStates()\n            //infoScrollableView.setFrameSize(NSSize(width: infoScrollableView.frame.width, height: infoCommonView.frame.height + infoDateView.frame.height))\n        case .battery:\n            infoScrollableView.addSubview(infoBatteryView)\n            infoBatteryView.frame.origin.y = infoCommonView.frame.height\n            infoBatteryView.setStates()\n            //infoScrollableView.setFrameSize(NSSize(width: infoScrollableView.frame.width, height: infoCommonView.frame.height + infoBatteryView.frame.height))\n        case .updates:\n            break\n        case .weather:\n            infoScrollableView.addSubview(infoWeatherView)\n            infoWeatherView.frame.origin.y = infoCommonView.frame.height\n            infoWeatherView.setStates()\n            //infoScrollableView.setFrameSize(NSSize(width: infoScrollableView.frame.width, height: infoCommonView.frame.height + infoWeatherView.frame.height))\n        case .countdown:\n            infoScrollableView.addSubview(infoCountdownView)\n            infoCountdownView.frame.origin.y = infoCommonView.frame.height\n            infoCountdownView.setStates()\n            //infoScrollableView.setFrameSize(NSSize(width: infoScrollableView.frame.width, height: infoCommonView.frame.height + infoCountdownView.frame.height))\n        case .timer:\n            infoScrollableView.addSubview(infoTimerView)\n            infoTimerView.frame.origin.y = infoCommonView.frame.height\n            infoTimerView.setStates()\n            //infoScrollableView.setFrameSize(NSSize(width: infoScrollableView.frame.width, height: infoCommonView.frame.height + infoTimerView.frame.height))\n        case .music:\n            infoScrollableView.addSubview(infoMusicView)\n            infoMusicView.frame.origin.y = infoCommonView.frame.height\n            infoMusicView.setStates()\n            //infoScrollableView.setFrameSize(NSSize(width: infoScrollableView.frame.width, height: infoCommonView.frame.height + infoMusicView.frame.height))\n        }\n        \n        infoScrollView.documentView?.scroll(.zero)\n\n    }\n\n    func addSubMessagePanel() {\n        switch PrefsInfo.message.messageType {\n        case .text:\n            infoScrollableView.addSubview(infoMessageTextView)\n            infoMessageTextView.frame.origin.y = infoCommonView.frame.height + infoMessageView.frame.height\n            currentSubMessage = infoMessageTextView\n        case .shell:\n            infoScrollableView.addSubview(infoMessageShellView)\n            infoMessageShellView.frame.origin.y = infoCommonView.frame.height + infoMessageView.frame.height\n            currentSubMessage = infoMessageShellView\n        case .textfile:\n            infoScrollableView.addSubview(infoMessageTextFileView)\n            infoMessageTextFileView.frame.origin.y = infoCommonView.frame.height + infoMessageView.frame.height\n            currentSubMessage = infoMessageTextFileView\n        }\n\n        infoMessageTextView.frame.origin.y = infoCommonView.frame.height + infoMessageView.frame.height\n    }\n\n    // We call this when we switch from one mode  to another\n    public func switchSubMessagePanel() {\n        if let cMessage = currentSubMessage {\n            cMessage.removeFromSuperview()\n        }\n\n        addSubMessagePanel()\n    }\n\n    // Clear the panel\n    func resetInfoPanel() {\n        infoScrollableView.subviews.forEach({ $0.removeFromSuperview() })\n    }\n\n    // MARK: Weather panel\n    // Simple current conditions\n    func openWeatherPreview(weather: OWeather) {\n        if !weatherPanel.isVisible {\n            weatherPanel.makeKeyAndOrderFront(self)\n        }\n\n        weatherLabel.stringValue = \"\\(String(describing: weather.name)) \\n\\n \\(weather)\"\n        let cond = ConditionLayer(condition: weather, scale: 2.0)\n\n        weatherCustomView.layer = cond\n        weatherCustomView.wantsLayer = true\n    }\n\n    // Forecasts\n    func openWeatherPreview(weather: ForecastElement) {\n        if !weatherPanel.isVisible {\n            weatherPanel.makeKeyAndOrderFront(self)\n        }\n\n        weatherLabel.stringValue = \"\\(weather)\"\n        let cond = ForecastLayer(condition: weather, scale: 2.0)\n\n        weatherCustomView.layer = cond\n        weatherCustomView.wantsLayer = true\n    }\n\n    @IBAction func helpWeatherButtonClick(_ button: NSButton) {\n        popoverWeather.show(relativeTo: button.preparedContentRect, of: button, preferredEdge: .maxY)\n    }\n}\n"
  },
  {
    "path": "Resources/MainUI/Settings panels/OverlaysViewController.xib",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.Cocoa.XIB\" version=\"3.0\" toolsVersion=\"23094\" targetRuntime=\"MacOSX.Cocoa\" propertyAccessControl=\"none\" useAutolayout=\"YES\" customObjectInstantitationMethod=\"direct\">\n    <dependencies>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.CocoaPlugin\" version=\"23094\"/>\n        <capability name=\"Image references\" minToolsVersion=\"12.0\"/>\n        <capability name=\"System colors introduced in macOS 10.14\" minToolsVersion=\"10.0\"/>\n        <capability name=\"documents saved in the Xcode 8 format\" minToolsVersion=\"8.0\"/>\n    </dependencies>\n    <objects>\n        <customObject id=\"-2\" userLabel=\"File's Owner\" customClass=\"OverlaysViewController\" customModule=\"Aerial\" customModuleProvider=\"target\">\n            <connections>\n                <outlet property=\"fontButton\" destination=\"PoK-PJ-h6f\" id=\"cfO-6g-shd\"/>\n                <outlet property=\"hideUnderCompanion\" destination=\"9LV-pU-dEq\" id=\"Y6D-Az-0fK\"/>\n                <outlet property=\"infoBatteryView\" destination=\"d6p-Wj-XTq\" id=\"TOA-QY-ml7\"/>\n                <outlet property=\"infoClockView\" destination=\"OyK-gu-5yP\" id=\"WS7-hd-gZO\"/>\n                <outlet property=\"infoCommonView\" destination=\"T8p-iy-4mZ\" id=\"O6Q-6D-auu\"/>\n                <outlet property=\"infoCountdownView\" destination=\"OhT-fX-ti2\" id=\"xUS-Gc-HhU\"/>\n                <outlet property=\"infoDateView\" destination=\"uc4-YQ-4ov\" id=\"jmw-3I-Jdg\"/>\n                <outlet property=\"infoLocationView\" destination=\"UAz-72-SHK\" id=\"oW2-oX-deu\"/>\n                <outlet property=\"infoMessageShellView\" destination=\"bXW-hw-1fP\" id=\"uOb-VI-ClK\"/>\n                <outlet property=\"infoMessageTextFileView\" destination=\"dIH-yk-sga\" id=\"s34-LA-6NG\"/>\n                <outlet property=\"infoMessageTextView\" destination=\"eaZ-HA-6Kx\" id=\"f5W-Be-GRk\"/>\n                <outlet property=\"infoMessageView\" destination=\"wFi-1P-F0m\" id=\"TSS-kq-QgP\"/>\n                <outlet property=\"infoMusicView\" destination=\"ixa-6o-Glt\" id=\"Gqv-EY-bU1\"/>\n                <outlet property=\"infoScrollView\" destination=\"sMA-U2-JnG\" id=\"GCA-NS-LgC\"/>\n                <outlet property=\"infoScrollableView\" destination=\"y2b-67-Tqj\" id=\"5M2-UL-aZx\"/>\n                <outlet property=\"infoSettingsTableView\" destination=\"d1q-xb-ZLa\" id=\"11p-YY-Bgo\"/>\n                <outlet property=\"infoSettingsView\" destination=\"GtU-uK-2NN\" id=\"Y8M-WL-3Be\"/>\n                <outlet property=\"infoTableView\" destination=\"gvl-yV-dFx\" id=\"bUj-jT-0xJ\"/>\n                <outlet property=\"infoTimerView\" destination=\"VcD-4g-CvS\" id=\"qj2-sX-DzL\"/>\n                <outlet property=\"infoWeatherView\" destination=\"cmR-hZ-0Fe\" id=\"zIn-Z8-lfo\"/>\n                <outlet property=\"popoverWeather\" destination=\"mNc-DU-HEx\" id=\"JaA-P6-Tgl\"/>\n                <outlet property=\"trashButton\" destination=\"JnO-I8-Uqt\" id=\"K63-kl-sep\"/>\n                <outlet property=\"view\" destination=\"Hz6-mo-xeY\" id=\"0bl-1N-x8E\"/>\n                <outlet property=\"weatherCustomView\" destination=\"gfx-ZG-teS\" id=\"9O8-uI-GgY\"/>\n                <outlet property=\"weatherLabel\" destination=\"3Z6-oE-76I\" id=\"irt-l5-8IG\"/>\n                <outlet property=\"weatherPanel\" destination=\"T1o-cz-8zC\" id=\"Yp7-Gx-LSc\"/>\n            </connections>\n        </customObject>\n        <customObject id=\"-1\" userLabel=\"First Responder\" customClass=\"FirstResponder\"/>\n        <customObject id=\"-3\" userLabel=\"Application\" customClass=\"NSObject\"/>\n        <customView translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Hz6-mo-xeY\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"811\" height=\"530\"/>\n            <subviews>\n                <scrollView autohidesScrollers=\"YES\" horizontalLineScroll=\"32\" horizontalPageScroll=\"10\" verticalLineScroll=\"32\" verticalPageScroll=\"10\" usesPredominantAxisScrolling=\"NO\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Zk3-dp-nQh\">\n                    <rect key=\"frame\" x=\"0.0\" y=\"33\" width=\"180\" height=\"445\"/>\n                    <clipView key=\"contentView\" drawsBackground=\"NO\" id=\"3a0-nz-lxc\">\n                        <rect key=\"frame\" x=\"1\" y=\"1\" width=\"178\" height=\"443\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <subviews>\n                            <tableView verticalHuggingPriority=\"750\" allowsExpansionToolTips=\"YES\" columnReordering=\"NO\" columnResizing=\"NO\" multipleSelection=\"NO\" emptySelection=\"NO\" autosaveColumns=\"NO\" typeSelect=\"NO\" rowHeight=\"30\" rowSizeStyle=\"automatic\" viewBased=\"YES\" id=\"gvl-yV-dFx\">\n                                <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"178\" height=\"443\"/>\n                                <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                                <size key=\"intercellSpacing\" width=\"3\" height=\"2\"/>\n                                <color key=\"backgroundColor\" name=\"controlBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                <color key=\"gridColor\" name=\"gridColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                <tableColumns>\n                                    <tableColumn width=\"139\" minWidth=\"100\" maxWidth=\"5000\" id=\"VOh-3F-i8i\">\n                                        <tableHeaderCell key=\"headerCell\" lineBreakMode=\"truncatingTail\" borderStyle=\"border\">\n                                            <color key=\"textColor\" name=\"headerTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                            <color key=\"backgroundColor\" name=\"headerColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                        </tableHeaderCell>\n                                        <textFieldCell key=\"dataCell\" lineBreakMode=\"truncatingTail\" selectable=\"YES\" editable=\"YES\" sendsActionOnEndEditing=\"YES\" title=\"Text\" id=\"MTT-4z-BwK\">\n                                            <font key=\"font\" metaFont=\"system\"/>\n                                            <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                            <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                        </textFieldCell>\n                                        <tableColumnResizingMask key=\"resizingMask\" resizeWithTable=\"YES\" userResizable=\"YES\"/>\n                                        <prototypeCellViews>\n                                            <tableCellView identifier=\"InfoSourceCellID\" id=\"z2K-es-FwZ\">\n                                                <rect key=\"frame\" x=\"1\" y=\"1\" width=\"144\" height=\"30\"/>\n                                                <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                                                <subviews>\n                                                    <imageView horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"bdb-n8-tf9\">\n                                                        <rect key=\"frame\" x=\"3\" y=\"7\" width=\"17\" height=\"17\"/>\n                                                        <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\" flexibleMaxY=\"YES\"/>\n                                                        <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" image=\"NSStatusAvailable\" id=\"fyj-we-pry\"/>\n                                                    </imageView>\n                                                    <textField focusRingType=\"none\" verticalHuggingPriority=\"750\" horizontalCompressionResistancePriority=\"250\" fixedFrame=\"YES\" allowsExpansionToolTips=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"ZPf-XD-9bz\">\n                                                        <rect key=\"frame\" x=\"25\" y=\"8\" width=\"119\" height=\"17\"/>\n                                                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" flexibleMinY=\"YES\" flexibleMaxY=\"YES\"/>\n                                                        <textFieldCell key=\"cell\" lineBreakMode=\"truncatingTail\" sendsActionOnEndEditing=\"YES\" title=\"Table View Cell\" id=\"Sxx-cb-kU6\">\n                                                            <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                                            <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                            <color key=\"backgroundColor\" name=\"controlColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                        </textFieldCell>\n                                                    </textField>\n                                                </subviews>\n                                                <connections>\n                                                    <outlet property=\"imageView\" destination=\"bdb-n8-tf9\" id=\"XSa-50-pg7\"/>\n                                                    <outlet property=\"textField\" destination=\"ZPf-XD-9bz\" id=\"Lt9-sm-Ibq\"/>\n                                                </connections>\n                                            </tableCellView>\n                                        </prototypeCellViews>\n                                    </tableColumn>\n                                    <tableColumn width=\"24\" minWidth=\"24\" maxWidth=\"24\" id=\"XfJ-iU-882\">\n                                        <tableHeaderCell key=\"headerCell\" lineBreakMode=\"truncatingTail\" borderStyle=\"border\" alignment=\"left\">\n                                            <color key=\"textColor\" name=\"headerTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                            <color key=\"backgroundColor\" white=\"0.0\" alpha=\"0.0\" colorSpace=\"custom\" customColorSpace=\"genericGamma22GrayColorSpace\"/>\n                                        </tableHeaderCell>\n                                        <textFieldCell key=\"dataCell\" lineBreakMode=\"truncatingTail\" selectable=\"YES\" editable=\"YES\" alignment=\"left\" title=\"Text Cell\" id=\"Tgq-qi-yKt\">\n                                            <font key=\"font\" metaFont=\"system\"/>\n                                            <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                            <color key=\"backgroundColor\" name=\"controlBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                        </textFieldCell>\n                                        <tableColumnResizingMask key=\"resizingMask\" resizeWithTable=\"YES\" userResizable=\"YES\"/>\n                                        <prototypeCellViews>\n                                            <tableCellView identifier=\"InfoSourceGripID\" id=\"mqK-lA-asj\">\n                                                <rect key=\"frame\" x=\"148\" y=\"1\" width=\"28\" height=\"30\"/>\n                                                <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                                                <subviews>\n                                                    <imageView horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"iJz-xW-cYh\">\n                                                        <rect key=\"frame\" x=\"3\" y=\"7\" width=\"17.5\" height=\"17\"/>\n                                                        <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\" flexibleMaxY=\"YES\"/>\n                                                        <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" image=\"NSListViewTemplate\" id=\"6a7-o7-83i\"/>\n                                                    </imageView>\n                                                    <textField focusRingType=\"none\" verticalHuggingPriority=\"750\" horizontalCompressionResistancePriority=\"250\" fixedFrame=\"YES\" allowsExpansionToolTips=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"JG8-tu-Vz5\">\n                                                        <rect key=\"frame\" x=\"23\" y=\"13\" width=\"8\" height=\"17\"/>\n                                                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" flexibleMinY=\"YES\"/>\n                                                        <textFieldCell key=\"cell\" lineBreakMode=\"truncatingTail\" sendsActionOnEndEditing=\"YES\" title=\"Table View Cell\" id=\"sep-9A-0Ae\">\n                                                            <font key=\"font\" metaFont=\"system\"/>\n                                                            <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                            <color key=\"backgroundColor\" name=\"controlColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                        </textFieldCell>\n                                                    </textField>\n                                                </subviews>\n                                                <connections>\n                                                    <outlet property=\"imageView\" destination=\"iJz-xW-cYh\" id=\"hhp-TE-rqF\"/>\n                                                    <outlet property=\"textField\" destination=\"JG8-tu-Vz5\" id=\"cP4-uy-PIy\"/>\n                                                </connections>\n                                            </tableCellView>\n                                        </prototypeCellViews>\n                                    </tableColumn>\n                                </tableColumns>\n                            </tableView>\n                        </subviews>\n                        <nil key=\"backgroundColor\"/>\n                    </clipView>\n                    <constraints>\n                        <constraint firstAttribute=\"width\" constant=\"180\" id=\"Mga-Ck-cNd\"/>\n                    </constraints>\n                    <scroller key=\"horizontalScroller\" hidden=\"YES\" wantsLayer=\"YES\" verticalHuggingPriority=\"750\" doubleValue=\"0.080000000000000002\" horizontal=\"YES\" id=\"7ap-mS-r5O\">\n                        <rect key=\"frame\" x=\"1\" y=\"332\" width=\"178\" height=\"16\"/>\n                        <autoresizingMask key=\"autoresizingMask\"/>\n                    </scroller>\n                    <scroller key=\"verticalScroller\" hidden=\"YES\" wantsLayer=\"YES\" verticalHuggingPriority=\"750\" horizontal=\"NO\" id=\"u3m-Ce-0wj\">\n                        <rect key=\"frame\" x=\"224\" y=\"17\" width=\"15\" height=\"102\"/>\n                        <autoresizingMask key=\"autoresizingMask\"/>\n                    </scroller>\n                </scrollView>\n                <scrollView autohidesScrollers=\"YES\" horizontalLineScroll=\"31\" horizontalPageScroll=\"10\" verticalLineScroll=\"31\" verticalPageScroll=\"10\" hasHorizontalScroller=\"NO\" hasVerticalScroller=\"NO\" usesPredominantAxisScrolling=\"NO\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Yug-di-Rrj\">\n                    <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"180\" height=\"33\"/>\n                    <clipView key=\"contentView\" id=\"cUU-VJ-Apk\">\n                        <rect key=\"frame\" x=\"1\" y=\"1\" width=\"178\" height=\"31\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <subviews>\n                            <tableView verticalHuggingPriority=\"750\" allowsExpansionToolTips=\"YES\" columnAutoresizingStyle=\"none\" columnReordering=\"NO\" columnSelection=\"YES\" columnResizing=\"NO\" multipleSelection=\"NO\" autosaveColumns=\"NO\" rowHeight=\"29\" rowSizeStyle=\"automatic\" viewBased=\"YES\" id=\"d1q-xb-ZLa\">\n                                <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"178\" height=\"31\"/>\n                                <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                                <size key=\"intercellSpacing\" width=\"3\" height=\"2\"/>\n                                <color key=\"backgroundColor\" name=\"controlBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                <color key=\"gridColor\" name=\"gridColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                <tableColumns>\n                                    <tableColumn width=\"137\" minWidth=\"40\" maxWidth=\"1000\" id=\"4da-TV-VtV\">\n                                        <tableHeaderCell key=\"headerCell\" lineBreakMode=\"truncatingTail\" borderStyle=\"border\">\n                                            <color key=\"textColor\" name=\"headerTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                            <color key=\"backgroundColor\" name=\"headerColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                        </tableHeaderCell>\n                                        <imageCell key=\"dataCell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" id=\"NZr-AS-CeK\"/>\n                                        <tableColumnResizingMask key=\"resizingMask\" resizeWithTable=\"YES\" userResizable=\"YES\"/>\n                                        <prototypeCellViews>\n                                            <tableCellView identifier=\"InfoSettingsCellID\" id=\"oWo-vM-jes\">\n                                                <rect key=\"frame\" x=\"1\" y=\"1\" width=\"146\" height=\"29\"/>\n                                                <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                                                <subviews>\n                                                    <imageView horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"5da-Zj-6hn\">\n                                                        <rect key=\"frame\" x=\"3\" y=\"6\" width=\"17\" height=\"17\"/>\n                                                        <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\" flexibleMaxY=\"YES\"/>\n                                                        <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" image=\"NSFontPanel\" id=\"xTb-q3-dKI\"/>\n                                                    </imageView>\n                                                    <textField focusRingType=\"none\" verticalHuggingPriority=\"750\" horizontalCompressionResistancePriority=\"250\" fixedFrame=\"YES\" allowsExpansionToolTips=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"qoI-bd-SAT\">\n                                                        <rect key=\"frame\" x=\"25\" y=\"7\" width=\"121\" height=\"17\"/>\n                                                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" flexibleMinY=\"YES\" flexibleMaxY=\"YES\"/>\n                                                        <textFieldCell key=\"cell\" lineBreakMode=\"truncatingTail\" sendsActionOnEndEditing=\"YES\" title=\"Table View Cell\" id=\"HdC-e7-iKl\">\n                                                            <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                                            <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                            <color key=\"backgroundColor\" name=\"controlColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                        </textFieldCell>\n                                                    </textField>\n                                                </subviews>\n                                                <connections>\n                                                    <outlet property=\"imageView\" destination=\"5da-Zj-6hn\" id=\"o55-E3-vY4\"/>\n                                                    <outlet property=\"textField\" destination=\"qoI-bd-SAT\" id=\"khP-4a-sJo\"/>\n                                                </connections>\n                                            </tableCellView>\n                                        </prototypeCellViews>\n                                    </tableColumn>\n                                </tableColumns>\n                            </tableView>\n                        </subviews>\n                    </clipView>\n                    <constraints>\n                        <constraint firstAttribute=\"height\" constant=\"33\" id=\"GRf-JG-Pdu\"/>\n                        <constraint firstAttribute=\"width\" constant=\"180\" id=\"o0A-ZK-35T\"/>\n                    </constraints>\n                    <scroller key=\"horizontalScroller\" hidden=\"YES\" wantsLayer=\"YES\" verticalHuggingPriority=\"750\" horizontal=\"YES\" id=\"q1t-3j-3Pv\">\n                        <rect key=\"frame\" x=\"-100\" y=\"-100\" width=\"161\" height=\"16\"/>\n                        <autoresizingMask key=\"autoresizingMask\"/>\n                    </scroller>\n                    <scroller key=\"verticalScroller\" hidden=\"YES\" wantsLayer=\"YES\" verticalHuggingPriority=\"750\" horizontal=\"NO\" id=\"z2k-pl-D9Z\">\n                        <rect key=\"frame\" x=\"-100\" y=\"-100\" width=\"15\" height=\"102\"/>\n                        <autoresizingMask key=\"autoresizingMask\"/>\n                    </scroller>\n                </scrollView>\n                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"gfE-bm-FTe\">\n                    <rect key=\"frame\" x=\"52\" y=\"497\" width=\"363\" height=\"17\"/>\n                    <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"Select which information should be overlayed on videos\" id=\"dKT-nu-F64\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <imageView horizontalHuggingPriority=\"25\" verticalHuggingPriority=\"25\" horizontalCompressionResistancePriority=\"75\" verticalCompressionResistancePriority=\"75\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"sjm-7w-iIw\">\n                    <rect key=\"frame\" x=\"16\" y=\"480\" width=\"28\" height=\"45\"/>\n                    <constraints>\n                        <constraint firstAttribute=\"height\" constant=\"34\" id=\"2fL-xS-TE1\"/>\n                        <constraint firstAttribute=\"width\" constant=\"28\" id=\"LVM-ht-Vpd\"/>\n                    </constraints>\n                    <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyUpOrDown\" id=\"477-pG-gQT\">\n                        <imageReference key=\"image\" image=\"text.bubble\" catalog=\"system\" symbolScale=\"large\"/>\n                    </imageCell>\n                    <color key=\"contentTintColor\" name=\"controlAccentColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                </imageView>\n                <scrollView horizontalLineScroll=\"10\" horizontalPageScroll=\"10\" verticalLineScroll=\"10\" verticalPageScroll=\"10\" usesPredominantAxisScrolling=\"NO\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"sMA-U2-JnG\">\n                    <rect key=\"frame\" x=\"188\" y=\"0.0\" width=\"623\" height=\"478\"/>\n                    <clipView key=\"contentView\" id=\"xUv-v2-rf1\">\n                        <rect key=\"frame\" x=\"1\" y=\"1\" width=\"621\" height=\"476\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <subviews>\n                            <view id=\"y2b-67-Tqj\" customClass=\"InfoContainerView\" customModule=\"Aerial\" customModuleProvider=\"target\">\n                                <rect key=\"frame\" x=\"0.0\" y=\"-345\" width=\"600\" height=\"806\"/>\n                                <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                            </view>\n                        </subviews>\n                    </clipView>\n                    <scroller key=\"horizontalScroller\" wantsLayer=\"YES\" verticalHuggingPriority=\"750\" horizontal=\"YES\" id=\"aWh-xa-Re2\">\n                        <rect key=\"frame\" x=\"1\" y=\"461\" width=\"621\" height=\"16\"/>\n                        <autoresizingMask key=\"autoresizingMask\"/>\n                    </scroller>\n                    <scroller key=\"verticalScroller\" wantsLayer=\"YES\" verticalHuggingPriority=\"750\" doubleValue=\"0.9939393939393939\" horizontal=\"NO\" id=\"fWU-BK-uie\">\n                        <rect key=\"frame\" x=\"606\" y=\"1\" width=\"16\" height=\"476\"/>\n                        <autoresizingMask key=\"autoresizingMask\"/>\n                    </scroller>\n                </scrollView>\n                <button toolTip=\"Enable or disable this overlay\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"9LV-pU-dEq\">\n                    <rect key=\"frame\" x=\"556\" y=\"494.5\" width=\"235\" height=\"22\"/>\n                    <buttonCell key=\"cell\" type=\"check\" title=\"Hide overlays under Companion\" bezelStyle=\"regularSquare\" imagePosition=\"left\" controlSize=\"large\" state=\"on\" inset=\"2\" id=\"CRS-jP-1XT\">\n                        <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"hideUnderCompanionClick:\" target=\"-2\" id=\"5Q4-BD-WQ9\"/>\n                    </connections>\n                </button>\n            </subviews>\n            <constraints>\n                <constraint firstItem=\"sMA-U2-JnG\" firstAttribute=\"leading\" secondItem=\"Zk3-dp-nQh\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"0kC-0R-2xS\"/>\n                <constraint firstItem=\"Zk3-dp-nQh\" firstAttribute=\"top\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"top\" constant=\"52\" id=\"37G-4g-HfA\"/>\n                <constraint firstItem=\"sjm-7w-iIw\" firstAttribute=\"leading\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"leading\" constant=\"16\" id=\"4CX-Lg-Yzy\"/>\n                <constraint firstAttribute=\"width\" relation=\"greaterThanOrEqual\" constant=\"811\" id=\"7j7-8G-gbn\"/>\n                <constraint firstAttribute=\"bottom\" secondItem=\"Yug-di-Rrj\" secondAttribute=\"bottom\" id=\"IVW-7y-lBp\"/>\n                <constraint firstAttribute=\"height\" relation=\"greaterThanOrEqual\" constant=\"530\" id=\"JtC-54-lLc\"/>\n                <constraint firstAttribute=\"bottom\" secondItem=\"sMA-U2-JnG\" secondAttribute=\"bottom\" id=\"SCF-fS-589\"/>\n                <constraint firstItem=\"Zk3-dp-nQh\" firstAttribute=\"leading\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"leading\" id=\"SR5-Ta-E7l\"/>\n                <constraint firstItem=\"9LV-pU-dEq\" firstAttribute=\"firstBaseline\" secondItem=\"gfE-bm-FTe\" secondAttribute=\"firstBaseline\" id=\"Twx-LD-P0d\"/>\n                <constraint firstItem=\"gfE-bm-FTe\" firstAttribute=\"top\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"top\" constant=\"16\" id=\"URk-WE-5c7\"/>\n                <constraint firstAttribute=\"trailing\" secondItem=\"sMA-U2-JnG\" secondAttribute=\"trailing\" id=\"ZnI-7H-uCH\"/>\n                <constraint firstItem=\"Yug-di-Rrj\" firstAttribute=\"leading\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"leading\" id=\"gVB-by-2eZ\"/>\n                <constraint firstItem=\"sMA-U2-JnG\" firstAttribute=\"top\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"top\" constant=\"52\" id=\"lRn-cJ-iU4\"/>\n                <constraint firstAttribute=\"trailing\" secondItem=\"9LV-pU-dEq\" secondAttribute=\"trailing\" constant=\"20\" id=\"ni9-zR-guf\"/>\n                <constraint firstItem=\"Yug-di-Rrj\" firstAttribute=\"top\" secondItem=\"Zk3-dp-nQh\" secondAttribute=\"bottom\" id=\"p10-kT-ics\"/>\n                <constraint firstItem=\"gfE-bm-FTe\" firstAttribute=\"leading\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"leading\" constant=\"54\" id=\"rza-aE-7ja\"/>\n                <constraint firstItem=\"sjm-7w-iIw\" firstAttribute=\"top\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"top\" constant=\"10\" id=\"wtk-k3-wQx\"/>\n            </constraints>\n            <point key=\"canvasLocation\" x=\"-49.5\" y=\"664.5\"/>\n        </customView>\n        <customView id=\"GtU-uK-2NN\" userLabel=\"Settings Extra View\" customClass=\"InfoSettingsView\" customModule=\"Aerial\" customModuleProvider=\"target\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"595\" height=\"394\"/>\n            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n            <subviews>\n                <popUpButton identifier=\"Duration of the fades for the text\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"G3P-fi-r9H\">\n                    <rect key=\"frame\" x=\"145\" y=\"349\" width=\"120\" height=\"40\"/>\n                    <popUpButtonCell key=\"cell\" type=\"push\" title=\"1 second\" bezelStyle=\"rounded\" alignment=\"left\" controlSize=\"large\" lineBreakMode=\"truncatingTail\" state=\"on\" borderStyle=\"borderAndBezel\" imageScaling=\"proportionallyDown\" inset=\"2\" selectedItem=\"x2L-HF-3HG\" id=\"qgj-oO-wcE\">\n                        <behavior key=\"behavior\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" size=\"14\" name=\"HelveticaNeue\"/>\n                        <menu key=\"menu\" id=\"oGb-7O-iZR\">\n                            <items>\n                                <menuItem title=\"None\" id=\"osX-gR-dkC\"/>\n                                <menuItem title=\"0.5 second\" id=\"ZOr-Yr-lRj\"/>\n                                <menuItem title=\"1 second\" state=\"on\" id=\"x2L-HF-3HG\"/>\n                                <menuItem title=\"2 seconds\" id=\"C9d-IB-gUc\">\n                                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                </menuItem>\n                            </items>\n                        </menu>\n                    </popUpButtonCell>\n                    <connections>\n                        <action selector=\"fadeInOutTextModePopupChange:\" target=\"GtU-uK-2NN\" id=\"mzb-eS-goj\"/>\n                    </connections>\n                </popUpButton>\n                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"ySi-eW-CSJ\">\n                    <rect key=\"frame\" x=\"64\" y=\"362\" width=\"80\" height=\"17\"/>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" alignment=\"right\" title=\"Fade in/out:\" id=\"ja1-t4-O35\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <button toolTip=\"Change the distance between the corner of the screen and where the descriptions should appear\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"su9-vv-ZAb\">\n                    <rect key=\"frame\" x=\"147\" y=\"269.5\" width=\"197\" height=\"22\"/>\n                    <buttonCell key=\"cell\" type=\"check\" title=\"Change margins to corner\" bezelStyle=\"regularSquare\" imagePosition=\"left\" controlSize=\"large\" inset=\"2\" id=\"Z9i-9m-7Pr\">\n                        <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"changeMarginsToCornerClick:\" target=\"GtU-uK-2NN\" id=\"oHb-BO-aAm\"/>\n                    </connections>\n                </button>\n                <textField toolTip=\"Horizontal margin\" focusRingType=\"none\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"kb5-p4-rHJ\">\n                    <rect key=\"frame\" x=\"150\" y=\"228\" width=\"60\" height=\"22\"/>\n                    <constraints>\n                        <constraint firstAttribute=\"width\" constant=\"60\" id=\"ueP-dL-zto\"/>\n                    </constraints>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" scrollable=\"YES\" lineBreakMode=\"clipping\" selectable=\"YES\" editable=\"YES\" continuous=\"YES\" enabled=\"NO\" sendsActionOnEndEditing=\"YES\" borderStyle=\"bezel\" drawsBackground=\"YES\" id=\"WQZ-Ym-zHN\">\n                        <numberFormatter key=\"formatter\" formatterBehavior=\"default10_4\" usesGroupingSeparator=\"NO\" groupingSize=\"0\" minimumIntegerDigits=\"0\" maximumIntegerDigits=\"42\" id=\"5HX-tv-rlI\">\n                            <real key=\"minimum\" value=\"0.0\"/>\n                        </numberFormatter>\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                    <connections>\n                        <action selector=\"marginXChange:\" target=\"GtU-uK-2NN\" id=\"XBK-op-c1l\"/>\n                    </connections>\n                </textField>\n                <textField toolTip=\"Vertical margin\" focusRingType=\"none\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"yzX-D0-NnG\">\n                    <rect key=\"frame\" x=\"327\" y=\"228\" width=\"60\" height=\"22\"/>\n                    <constraints>\n                        <constraint firstAttribute=\"width\" constant=\"60\" id=\"rs1-dq-lf9\"/>\n                    </constraints>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" scrollable=\"YES\" lineBreakMode=\"clipping\" selectable=\"YES\" editable=\"YES\" continuous=\"YES\" enabled=\"NO\" sendsActionOnEndEditing=\"YES\" borderStyle=\"bezel\" drawsBackground=\"YES\" id=\"say-AV-b65\">\n                        <numberFormatter key=\"formatter\" formatterBehavior=\"default10_4\" usesGroupingSeparator=\"NO\" groupingSize=\"0\" minimumIntegerDigits=\"0\" maximumIntegerDigits=\"42\" id=\"S0O-po-Ay7\">\n                            <real key=\"minimum\" value=\"0.0\"/>\n                        </numberFormatter>\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                    <connections>\n                        <action selector=\"marginYChange:\" target=\"GtU-uK-2NN\" id=\"ugD-iV-DFN\"/>\n                    </connections>\n                </textField>\n                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"HqZ-gX-ncy\">\n                    <rect key=\"frame\" x=\"69\" y=\"230\" width=\"75\" height=\"17\"/>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" alignment=\"right\" title=\"Horizontal:\" id=\"thr-pS-0jl\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"xxw-oy-I77\">\n                    <rect key=\"frame\" x=\"267\" y=\"230\" width=\"54\" height=\"16\"/>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" alignment=\"right\" title=\"Vertical:\" id=\"COM-73-TTT\">\n                        <font key=\"font\" metaFont=\"system\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <textField toolTip=\"Horizontal margin\" focusRingType=\"none\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"dZh-nK-0Gw\">\n                    <rect key=\"frame\" x=\"150\" y=\"55\" width=\"60\" height=\"22\"/>\n                    <constraints>\n                        <constraint firstAttribute=\"width\" constant=\"60\" id=\"yMq-dq-eGh\"/>\n                    </constraints>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" scrollable=\"YES\" lineBreakMode=\"clipping\" selectable=\"YES\" editable=\"YES\" continuous=\"YES\" sendsActionOnEndEditing=\"YES\" borderStyle=\"bezel\" drawsBackground=\"YES\" id=\"tj1-3W-MfE\">\n                        <numberFormatter key=\"formatter\" formatterBehavior=\"default10_4\" numberStyle=\"decimal\" formatWidth=\"-1\" minimumIntegerDigits=\"1\" maximumIntegerDigits=\"2000000000\" maximumFractionDigits=\"3\" id=\"WDP-2H-qLR\"/>\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                    <connections>\n                        <action selector=\"shadowOffsetXChange:\" target=\"GtU-uK-2NN\" id=\"kUt-BW-cve\"/>\n                    </connections>\n                </textField>\n                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"ZYn-IR-qoI\">\n                    <rect key=\"frame\" x=\"82\" y=\"57\" width=\"62\" height=\"17\"/>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" alignment=\"right\" title=\"Offset X:\" id=\"4UR-96-Ux7\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"1Bh-bU-E9Y\">\n                    <rect key=\"frame\" x=\"92\" y=\"143\" width=\"52\" height=\"17\"/>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" alignment=\"right\" title=\"Radius:\" id=\"Clf-LK-gxd\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <textField focusRingType=\"none\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"39A-Xd-EB7\">\n                    <rect key=\"frame\" x=\"150\" y=\"141\" width=\"60\" height=\"22\"/>\n                    <constraints>\n                        <constraint firstAttribute=\"width\" constant=\"60\" id=\"oui-G3-fXD\"/>\n                    </constraints>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" scrollable=\"YES\" lineBreakMode=\"clipping\" selectable=\"YES\" editable=\"YES\" sendsActionOnEndEditing=\"YES\" borderStyle=\"bezel\" drawsBackground=\"YES\" id=\"1GL-8Q-pQR\">\n                        <numberFormatter key=\"formatter\" formatterBehavior=\"default10_4\" numberStyle=\"decimal\" formatWidth=\"-1\" minimumIntegerDigits=\"1\" maximumIntegerDigits=\"2000000000\" maximumFractionDigits=\"3\" id=\"O4b-kP-liW\">\n                            <real key=\"minimum\" value=\"0.0\"/>\n                        </numberFormatter>\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                    <connections>\n                        <action selector=\"shadowRadiusChange:\" target=\"GtU-uK-2NN\" id=\"QmA-XO-ljW\"/>\n                    </connections>\n                </textField>\n                <slider verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"gcJ-WA-EWE\">\n                    <rect key=\"frame\" x=\"148\" y=\"93\" width=\"184\" height=\"28\"/>\n                    <constraints>\n                        <constraint firstAttribute=\"width\" constant=\"180\" id=\"n9E-I1-g2x\"/>\n                    </constraints>\n                    <sliderCell key=\"cell\" controlSize=\"large\" state=\"on\" alignment=\"left\" maxValue=\"100\" doubleValue=\"100\" tickMarkPosition=\"above\" numberOfTickMarks=\"5\" sliderType=\"linear\" id=\"x1P-OX-bVm\"/>\n                    <connections>\n                        <action selector=\"shadowOpacityChange:\" target=\"GtU-uK-2NN\" id=\"Ru4-mr-0hP\"/>\n                    </connections>\n                </slider>\n                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"4mF-Rh-AcU\">\n                    <rect key=\"frame\" x=\"85\" y=\"102\" width=\"59\" height=\"17\"/>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" alignment=\"right\" title=\"Opacity:\" id=\"NJu-aF-uQU\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <box verticalHuggingPriority=\"750\" boxType=\"separator\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"vtI-Ku-GlA\">\n                    <rect key=\"frame\" x=\"20\" y=\"209\" width=\"555\" height=\"5\"/>\n                </box>\n                <box verticalHuggingPriority=\"750\" boxType=\"separator\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"MNn-wF-5ps\">\n                    <rect key=\"frame\" x=\"20\" y=\"303\" width=\"555\" height=\"5\"/>\n                </box>\n                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"AuC-BT-A1Y\">\n                    <rect key=\"frame\" x=\"216\" y=\"230\" width=\"25\" height=\"17\"/>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" title=\"pts\" id=\"JiG-z5-cqQ\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"XBh-jk-U2r\">\n                    <rect key=\"frame\" x=\"393\" y=\"230\" width=\"25\" height=\"17\"/>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" title=\"pts\" id=\"5UN-ZC-90N\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"zie-Ij-Cja\">\n                    <rect key=\"frame\" x=\"216\" y=\"143\" width=\"24\" height=\"16\"/>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" title=\"pts\" id=\"yKV-IQ-8m6\">\n                        <font key=\"font\" metaFont=\"system\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"GbP-Rj-hee\">\n                    <rect key=\"frame\" x=\"216\" y=\"57\" width=\"25\" height=\"17\"/>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" title=\"pts\" id=\"dpj-dr-cJl\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <button hidden=\"YES\" toolTip=\"Reset the defaultt for the shadow settings\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"OcT-DR-8E0\">\n                    <rect key=\"frame\" x=\"144\" y=\"5\" width=\"142\" height=\"40\"/>\n                    <buttonCell key=\"cell\" type=\"push\" title=\"Reset to defaults\" bezelStyle=\"rounded\" alignment=\"center\" controlSize=\"large\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"yjH-mA-i9Z\">\n                        <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                    </buttonCell>\n                </button>\n                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"ysW-Rg-tzQ\">\n                    <rect key=\"frame\" x=\"148\" y=\"179\" width=\"182\" height=\"16\"/>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" alignment=\"left\" title=\"Adjust shadow appareances\" id=\"iqV-ef-tvA\">\n                        <font key=\"font\" metaFont=\"systemSemibold\" size=\"13\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"K6D-Z1-PuI\">\n                    <rect key=\"frame\" x=\"147\" y=\"319.5\" width=\"358\" height=\"22\"/>\n                    <buttonCell key=\"cell\" type=\"check\" title=\"High quality text rendering (may cause slowdowns)\" bezelStyle=\"regularSquare\" imagePosition=\"left\" controlSize=\"large\" inset=\"2\" id=\"cAs-le-MAS\">\n                        <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"highQualityTextRenderingChange:\" target=\"GtU-uK-2NN\" id=\"tmp-DZ-LVl\"/>\n                    </connections>\n                </button>\n                <textField toolTip=\"Vertical margin\" focusRingType=\"none\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"yNU-7H-rb7\">\n                    <rect key=\"frame\" x=\"330\" y=\"55\" width=\"60\" height=\"22\"/>\n                    <constraints>\n                        <constraint firstAttribute=\"width\" constant=\"60\" id=\"dfj-jf-MAH\"/>\n                    </constraints>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" scrollable=\"YES\" lineBreakMode=\"clipping\" selectable=\"YES\" editable=\"YES\" continuous=\"YES\" sendsActionOnEndEditing=\"YES\" borderStyle=\"bezel\" drawsBackground=\"YES\" id=\"gUR-tY-ktf\">\n                        <numberFormatter key=\"formatter\" formatterBehavior=\"default10_4\" numberStyle=\"decimal\" formatWidth=\"-1\" minimumIntegerDigits=\"1\" maximumIntegerDigits=\"2000000000\" maximumFractionDigits=\"3\" id=\"Mln-n5-yr9\"/>\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                    <connections>\n                        <action selector=\"shadowOffsetYChange:\" target=\"GtU-uK-2NN\" id=\"hz1-Ga-qid\"/>\n                    </connections>\n                </textField>\n                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"76z-KQ-kMx\">\n                    <rect key=\"frame\" x=\"267\" y=\"57\" width=\"57\" height=\"16\"/>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" alignment=\"right\" title=\"Offset Y:\" id=\"ykK-Vd-Q2G\">\n                        <font key=\"font\" metaFont=\"system\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"yTU-mB-Z1k\">\n                    <rect key=\"frame\" x=\"396\" y=\"57\" width=\"25\" height=\"17\"/>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" title=\"pts\" id=\"dXx-dy-UGV\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n            </subviews>\n            <constraints>\n                <constraint firstItem=\"su9-vv-ZAb\" firstAttribute=\"leading\" secondItem=\"G3P-fi-r9H\" secondAttribute=\"leading\" id=\"08v-ag-SDV\"/>\n                <constraint firstAttribute=\"trailing\" secondItem=\"vtI-Ku-GlA\" secondAttribute=\"trailing\" constant=\"20\" symbolic=\"YES\" id=\"0h0-qs-o6A\"/>\n                <constraint firstItem=\"dZh-nK-0Gw\" firstAttribute=\"leading\" secondItem=\"G3P-fi-r9H\" secondAttribute=\"leading\" id=\"12O-d8-eCh\"/>\n                <constraint firstItem=\"dZh-nK-0Gw\" firstAttribute=\"top\" secondItem=\"gcJ-WA-EWE\" secondAttribute=\"bottom\" constant=\"22\" id=\"27h-ww-WYK\"/>\n                <constraint firstItem=\"gcJ-WA-EWE\" firstAttribute=\"leading\" secondItem=\"G3P-fi-r9H\" secondAttribute=\"leading\" id=\"2fG-Vl-7gT\"/>\n                <constraint firstItem=\"yNU-7H-rb7\" firstAttribute=\"leading\" secondItem=\"76z-KQ-kMx\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"3SR-WD-u4O\"/>\n                <constraint firstItem=\"39A-Xd-EB7\" firstAttribute=\"leading\" secondItem=\"1Bh-bU-E9Y\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"3ZL-BH-wNX\"/>\n                <constraint firstItem=\"gcJ-WA-EWE\" firstAttribute=\"top\" secondItem=\"39A-Xd-EB7\" secondAttribute=\"bottom\" constant=\"22\" id=\"6CS-fP-zZg\"/>\n                <constraint firstItem=\"39A-Xd-EB7\" firstAttribute=\"leading\" secondItem=\"G3P-fi-r9H\" secondAttribute=\"leading\" id=\"6hE-wk-ii3\"/>\n                <constraint firstItem=\"xxw-oy-I77\" firstAttribute=\"baseline\" secondItem=\"XBh-jk-U2r\" secondAttribute=\"baseline\" id=\"7RV-7W-46E\"/>\n                <constraint firstItem=\"yNU-7H-rb7\" firstAttribute=\"firstBaseline\" secondItem=\"76z-KQ-kMx\" secondAttribute=\"firstBaseline\" id=\"Abq-A4-RLY\"/>\n                <constraint firstItem=\"OcT-DR-8E0\" firstAttribute=\"top\" secondItem=\"dZh-nK-0Gw\" secondAttribute=\"bottom\" constant=\"16\" id=\"Apa-ZL-wWz\"/>\n                <constraint firstItem=\"xxw-oy-I77\" firstAttribute=\"baseline\" secondItem=\"AuC-BT-A1Y\" secondAttribute=\"baseline\" id=\"BFK-K6-eKe\"/>\n                <constraint firstItem=\"kb5-p4-rHJ\" firstAttribute=\"top\" secondItem=\"su9-vv-ZAb\" secondAttribute=\"bottom\" constant=\"22\" id=\"CA5-py-12s\"/>\n                <constraint firstItem=\"ysW-Rg-tzQ\" firstAttribute=\"leading\" secondItem=\"GtU-uK-2NN\" secondAttribute=\"leading\" constant=\"150\" id=\"CNJ-Pr-Mhp\"/>\n                <constraint firstItem=\"gcJ-WA-EWE\" firstAttribute=\"leading\" secondItem=\"4mF-Rh-AcU\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"Chr-Hr-WMr\"/>\n                <constraint firstItem=\"kb5-p4-rHJ\" firstAttribute=\"leading\" secondItem=\"HqZ-gX-ncy\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"Drz-Sh-4NR\"/>\n                <constraint firstItem=\"G3P-fi-r9H\" firstAttribute=\"leading\" secondItem=\"ySi-eW-CSJ\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"ELi-w2-p7p\"/>\n                <constraint firstAttribute=\"bottom\" secondItem=\"OcT-DR-8E0\" secondAttribute=\"bottom\" constant=\"11\" id=\"FiA-cg-8ze\"/>\n                <constraint firstItem=\"su9-vv-ZAb\" firstAttribute=\"top\" secondItem=\"MNn-wF-5ps\" secondAttribute=\"bottom\" constant=\"16\" id=\"GHX-sV-QTq\"/>\n                <constraint firstItem=\"xxw-oy-I77\" firstAttribute=\"baseline\" secondItem=\"yzX-D0-NnG\" secondAttribute=\"baseline\" id=\"IEr-8M-c0T\"/>\n                <constraint firstItem=\"kb5-p4-rHJ\" firstAttribute=\"leading\" secondItem=\"G3P-fi-r9H\" secondAttribute=\"leading\" id=\"J3F-M8-Zav\"/>\n                <constraint firstItem=\"AuC-BT-A1Y\" firstAttribute=\"firstBaseline\" secondItem=\"kb5-p4-rHJ\" secondAttribute=\"firstBaseline\" id=\"MIE-4F-kld\"/>\n                <constraint firstItem=\"ysW-Rg-tzQ\" firstAttribute=\"top\" secondItem=\"vtI-Ku-GlA\" secondAttribute=\"bottom\" constant=\"16\" id=\"Mte-x5-4bq\"/>\n                <constraint firstItem=\"dZh-nK-0Gw\" firstAttribute=\"firstBaseline\" secondItem=\"ZYn-IR-qoI\" secondAttribute=\"firstBaseline\" id=\"Mwb-bO-nuM\"/>\n                <constraint firstItem=\"39A-Xd-EB7\" firstAttribute=\"firstBaseline\" secondItem=\"1Bh-bU-E9Y\" secondAttribute=\"firstBaseline\" id=\"Nda-R0-5Z8\"/>\n                <constraint firstItem=\"G3P-fi-r9H\" firstAttribute=\"leading\" secondItem=\"GtU-uK-2NN\" secondAttribute=\"leading\" constant=\"150\" id=\"OZr-uS-62v\"/>\n                <constraint firstItem=\"G3P-fi-r9H\" firstAttribute=\"top\" secondItem=\"GtU-uK-2NN\" secondAttribute=\"top\" constant=\"11\" id=\"Qvh-pT-ANZ\"/>\n                <constraint firstItem=\"dZh-nK-0Gw\" firstAttribute=\"leading\" secondItem=\"ZYn-IR-qoI\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"R5J-Ia-hSF\"/>\n                <constraint firstItem=\"xxw-oy-I77\" firstAttribute=\"leading\" secondItem=\"AuC-BT-A1Y\" secondAttribute=\"trailing\" constant=\"30\" id=\"RJR-Pe-UIJ\"/>\n                <constraint firstItem=\"GbP-Rj-hee\" firstAttribute=\"leading\" secondItem=\"dZh-nK-0Gw\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"UDx-Nz-Cbc\"/>\n                <constraint firstItem=\"K6D-Z1-PuI\" firstAttribute=\"leading\" secondItem=\"G3P-fi-r9H\" secondAttribute=\"leading\" id=\"VE8-mA-tBP\"/>\n                <constraint firstItem=\"yTU-mB-Z1k\" firstAttribute=\"leading\" secondItem=\"yNU-7H-rb7\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"WFU-lH-MQl\"/>\n                <constraint firstItem=\"OcT-DR-8E0\" firstAttribute=\"leading\" secondItem=\"G3P-fi-r9H\" secondAttribute=\"leading\" id=\"X9b-SQ-Hd1\"/>\n                <constraint firstItem=\"yTU-mB-Z1k\" firstAttribute=\"firstBaseline\" secondItem=\"76z-KQ-kMx\" secondAttribute=\"firstBaseline\" id=\"Z2e-EL-KlZ\"/>\n                <constraint firstItem=\"39A-Xd-EB7\" firstAttribute=\"top\" secondItem=\"ysW-Rg-tzQ\" secondAttribute=\"bottom\" constant=\"16\" id=\"ZTh-yK-r0r\"/>\n                <constraint firstItem=\"kb5-p4-rHJ\" firstAttribute=\"firstBaseline\" secondItem=\"HqZ-gX-ncy\" secondAttribute=\"firstBaseline\" id=\"aVX-jr-ze8\"/>\n                <constraint firstItem=\"zie-Ij-Cja\" firstAttribute=\"leading\" secondItem=\"39A-Xd-EB7\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"ase-3o-Z89\"/>\n                <constraint firstItem=\"XBh-jk-U2r\" firstAttribute=\"leading\" secondItem=\"yzX-D0-NnG\" secondAttribute=\"trailing\" constant=\"8\" id=\"bz2-fR-L8p\"/>\n                <constraint firstItem=\"76z-KQ-kMx\" firstAttribute=\"firstBaseline\" secondItem=\"GbP-Rj-hee\" secondAttribute=\"firstBaseline\" id=\"daT-QM-TGe\"/>\n                <constraint firstItem=\"vtI-Ku-GlA\" firstAttribute=\"top\" secondItem=\"kb5-p4-rHJ\" secondAttribute=\"bottom\" constant=\"16\" id=\"fcV-36-sKF\"/>\n                <constraint firstItem=\"yzX-D0-NnG\" firstAttribute=\"leading\" secondItem=\"xxw-oy-I77\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"g5P-I9-mhd\"/>\n                <constraint firstItem=\"GbP-Rj-hee\" firstAttribute=\"firstBaseline\" secondItem=\"ZYn-IR-qoI\" secondAttribute=\"firstBaseline\" id=\"lXZ-ck-vYE\"/>\n                <constraint firstItem=\"zie-Ij-Cja\" firstAttribute=\"firstBaseline\" secondItem=\"1Bh-bU-E9Y\" secondAttribute=\"firstBaseline\" id=\"lmE-QZ-WdJ\"/>\n                <constraint firstItem=\"vtI-Ku-GlA\" firstAttribute=\"leading\" secondItem=\"GtU-uK-2NN\" secondAttribute=\"leading\" constant=\"20\" symbolic=\"YES\" id=\"nTD-vU-omg\"/>\n                <constraint firstItem=\"76z-KQ-kMx\" firstAttribute=\"leading\" secondItem=\"GbP-Rj-hee\" secondAttribute=\"trailing\" constant=\"30\" id=\"oBl-Yb-ZNl\"/>\n                <constraint firstItem=\"AuC-BT-A1Y\" firstAttribute=\"leading\" secondItem=\"kb5-p4-rHJ\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"qGy-YV-vbx\"/>\n                <constraint firstItem=\"K6D-Z1-PuI\" firstAttribute=\"top\" secondItem=\"G3P-fi-r9H\" secondAttribute=\"bottom\" constant=\"16\" id=\"uOc-JJ-PUU\"/>\n                <constraint firstItem=\"gcJ-WA-EWE\" firstAttribute=\"firstBaseline\" secondItem=\"4mF-Rh-AcU\" secondAttribute=\"firstBaseline\" id=\"vAE-Pw-Vv0\"/>\n                <constraint firstItem=\"G3P-fi-r9H\" firstAttribute=\"firstBaseline\" secondItem=\"ySi-eW-CSJ\" secondAttribute=\"firstBaseline\" id=\"woW-pD-ZhP\"/>\n                <constraint firstItem=\"MNn-wF-5ps\" firstAttribute=\"leading\" secondItem=\"GtU-uK-2NN\" secondAttribute=\"leading\" constant=\"20\" symbolic=\"YES\" id=\"wqX-0G-bZr\"/>\n                <constraint firstAttribute=\"trailing\" secondItem=\"MNn-wF-5ps\" secondAttribute=\"trailing\" constant=\"20\" symbolic=\"YES\" id=\"xyC-SC-akq\"/>\n                <constraint firstItem=\"MNn-wF-5ps\" firstAttribute=\"top\" secondItem=\"K6D-Z1-PuI\" secondAttribute=\"bottom\" constant=\"16\" id=\"yY1-ve-A7q\"/>\n            </constraints>\n            <connections>\n                <outlet property=\"changeCornerMargins\" destination=\"su9-vv-ZAb\" id=\"Iat-b9-Py0\"/>\n                <outlet property=\"fadeInOutTextModePopup\" destination=\"G3P-fi-r9H\" id=\"oKr-m9-uuB\"/>\n                <outlet property=\"highQualityTextRendering\" destination=\"K6D-Z1-PuI\" id=\"GBA-yC-B52\"/>\n                <outlet property=\"marginHorizontalTextfield\" destination=\"kb5-p4-rHJ\" id=\"Ixp-jg-HDD\"/>\n                <outlet property=\"marginVerticalTextfield\" destination=\"yzX-D0-NnG\" id=\"zOA-Lw-ivP\"/>\n                <outlet property=\"shadowOffsetXFormatter\" destination=\"WDP-2H-qLR\" id=\"Cgb-OK-emD\"/>\n                <outlet property=\"shadowOffsetXTextfield\" destination=\"dZh-nK-0Gw\" id=\"cjj-sl-mYA\"/>\n                <outlet property=\"shadowOffsetYFormatter\" destination=\"Mln-n5-yr9\" id=\"G6P-No-sav\"/>\n                <outlet property=\"shadowOffsetYTextfield\" destination=\"yNU-7H-rb7\" id=\"wwP-sT-3bl\"/>\n                <outlet property=\"shadowOpacitySlider\" destination=\"gcJ-WA-EWE\" id=\"XtB-po-FAi\"/>\n                <outlet property=\"shadowRadiusFormatter\" destination=\"O4b-kP-liW\" id=\"wI3-2h-OBD\"/>\n                <outlet property=\"shadowRadiusTextField\" destination=\"39A-Xd-EB7\" id=\"YWj-xB-Rql\"/>\n            </connections>\n            <point key=\"canvasLocation\" x=\"-840\" y=\"1424\"/>\n        </customView>\n        <customView id=\"VcD-4g-CvS\" customClass=\"InfoTimerView\" customModule=\"Aerial\" customModuleProvider=\"target\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"580\" height=\"178\"/>\n            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n            <subviews>\n                <datePicker verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"gE6-mL-xQJ\">\n                    <rect key=\"frame\" x=\"150\" y=\"149\" width=\"66\" height=\"22\"/>\n                    <datePickerCell key=\"cell\" controlSize=\"large\" borderStyle=\"bezel\" alignment=\"left\" id=\"VJx-1x-ZEb\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <date key=\"date\" timeIntervalSinceReferenceDate=\"616845403.54662097\">\n                            <!--2020-07-19 09:56:43 +0000-->\n                        </date>\n                        <color key=\"backgroundColor\" name=\"controlBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <datePickerElements key=\"datePickerElements\" hour=\"YES\" minute=\"YES\" second=\"YES\"/>\n                    </datePickerCell>\n                    <connections>\n                        <action selector=\"durationChange:\" target=\"VcD-4g-CvS\" id=\"MIF-D3-MKE\"/>\n                    </connections>\n                </datePicker>\n                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"NzK-P4-GqX\">\n                    <rect key=\"frame\" x=\"80\" y=\"153\" width=\"64\" height=\"17\"/>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" alignment=\"right\" title=\"Duration:\" id=\"ro4-RK-m9b\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"gVp-r5-gaa\">\n                    <rect key=\"frame\" x=\"226\" y=\"150.5\" width=\"117\" height=\"22\"/>\n                    <buttonCell key=\"cell\" type=\"check\" title=\"With seconds\" bezelStyle=\"regularSquare\" imagePosition=\"left\" controlSize=\"large\" state=\"on\" inset=\"2\" id=\"nXA-rl-ef4\">\n                        <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"withSecondsClick:\" target=\"VcD-4g-CvS\" id=\"ueu-kE-m1v\"/>\n                    </connections>\n                </button>\n                <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"EeX-wh-JU0\">\n                    <rect key=\"frame\" x=\"147\" y=\"107.5\" width=\"232\" height=\"22\"/>\n                    <buttonCell key=\"cell\" type=\"check\" title=\"Disable for subsequent launchs\" bezelStyle=\"regularSquare\" imagePosition=\"left\" controlSize=\"large\" state=\"on\" inset=\"2\" id=\"xi5-dB-ZLe\">\n                        <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"disableWhenElapsedClick:\" target=\"VcD-4g-CvS\" id=\"bwB-qn-cKl\"/>\n                    </connections>\n                </button>\n                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"E21-aN-ze3\">\n                    <rect key=\"frame\" x=\"44\" y=\"110\" width=\"100\" height=\"17\"/>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" alignment=\"right\" title=\"When elapsed:\" id=\"U7L-lM-hqL\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"1Y7-SU-huu\">\n                    <rect key=\"frame\" x=\"147\" y=\"68.5\" width=\"215\" height=\"22\"/>\n                    <buttonCell key=\"cell\" type=\"check\" title=\"Replace timer with message:\" bezelStyle=\"regularSquare\" imagePosition=\"left\" controlSize=\"large\" state=\"on\" inset=\"2\" id=\"Vyj-GE-Y9f\">\n                        <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"replaceWithMessageClick:\" target=\"VcD-4g-CvS\" id=\"BmH-AQ-5Rv\"/>\n                    </connections>\n                </button>\n                <textField focusRingType=\"none\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"meA-O8-9VW\">\n                    <rect key=\"frame\" x=\"150\" y=\"27\" width=\"300\" height=\"22\"/>\n                    <constraints>\n                        <constraint firstAttribute=\"width\" constant=\"300\" id=\"NLg-Ly-vMJ\"/>\n                    </constraints>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" scrollable=\"YES\" lineBreakMode=\"clipping\" selectable=\"YES\" editable=\"YES\" enabled=\"NO\" sendsActionOnEndEditing=\"YES\" borderStyle=\"bezel\" placeholderString=\"Timer elapsed custom message\" drawsBackground=\"YES\" id=\"WjR-8a-ula\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                    <connections>\n                        <action selector=\"customMessageTextFieldChange:\" target=\"VcD-4g-CvS\" id=\"hVC-C3-wAI\"/>\n                    </connections>\n                </textField>\n            </subviews>\n            <constraints>\n                <constraint firstItem=\"gVp-r5-gaa\" firstAttribute=\"leading\" secondItem=\"gE6-mL-xQJ\" secondAttribute=\"trailing\" constant=\"16\" id=\"6z1-E9-zTL\"/>\n                <constraint firstItem=\"gE6-mL-xQJ\" firstAttribute=\"firstBaseline\" secondItem=\"NzK-P4-GqX\" secondAttribute=\"firstBaseline\" id=\"AaR-c5-GGO\"/>\n                <constraint firstItem=\"meA-O8-9VW\" firstAttribute=\"top\" secondItem=\"1Y7-SU-huu\" secondAttribute=\"bottom\" constant=\"22\" id=\"EOc-Sl-O69\"/>\n                <constraint firstItem=\"1Y7-SU-huu\" firstAttribute=\"leading\" secondItem=\"VcD-4g-CvS\" secondAttribute=\"leading\" constant=\"150\" id=\"Li3-ZM-2cK\"/>\n                <constraint firstItem=\"meA-O8-9VW\" firstAttribute=\"leading\" secondItem=\"VcD-4g-CvS\" secondAttribute=\"leading\" constant=\"150\" id=\"Zz8-B9-E3b\"/>\n                <constraint firstItem=\"1Y7-SU-huu\" firstAttribute=\"top\" secondItem=\"EeX-wh-JU0\" secondAttribute=\"bottom\" constant=\"22\" id=\"brn-TN-VgX\"/>\n                <constraint firstItem=\"EeX-wh-JU0\" firstAttribute=\"leading\" secondItem=\"E21-aN-ze3\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"gij-Fe-SKa\"/>\n                <constraint firstItem=\"EeX-wh-JU0\" firstAttribute=\"leading\" secondItem=\"VcD-4g-CvS\" secondAttribute=\"leading\" constant=\"150\" id=\"hkw-aF-mjz\"/>\n                <constraint firstItem=\"EeX-wh-JU0\" firstAttribute=\"firstBaseline\" secondItem=\"E21-aN-ze3\" secondAttribute=\"firstBaseline\" id=\"iCY-JZ-EMc\"/>\n                <constraint firstItem=\"gVp-r5-gaa\" firstAttribute=\"firstBaseline\" secondItem=\"NzK-P4-GqX\" secondAttribute=\"firstBaseline\" id=\"nve-hg-Rhe\"/>\n                <constraint firstItem=\"EeX-wh-JU0\" firstAttribute=\"top\" secondItem=\"gE6-mL-xQJ\" secondAttribute=\"bottom\" constant=\"22\" id=\"qgp-xh-3ao\"/>\n                <constraint firstItem=\"gE6-mL-xQJ\" firstAttribute=\"top\" secondItem=\"VcD-4g-CvS\" secondAttribute=\"top\" constant=\"11\" id=\"uhk-ep-gCQ\"/>\n                <constraint firstItem=\"gE6-mL-xQJ\" firstAttribute=\"leading\" secondItem=\"NzK-P4-GqX\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"xxo-Dw-z1d\"/>\n                <constraint firstItem=\"gE6-mL-xQJ\" firstAttribute=\"leading\" secondItem=\"VcD-4g-CvS\" secondAttribute=\"leading\" constant=\"150\" id=\"zD3-kE-rC1\"/>\n            </constraints>\n            <connections>\n                <outlet property=\"customMessageTextField\" destination=\"meA-O8-9VW\" id=\"mWs-g8-dJd\"/>\n                <outlet property=\"disableWhenElapsedCheckbox\" destination=\"EeX-wh-JU0\" id=\"OoT-yZ-s0a\"/>\n                <outlet property=\"durationTimePicker\" destination=\"gE6-mL-xQJ\" id=\"FXv-ky-qGf\"/>\n                <outlet property=\"replaceWithMessageCheckbox\" destination=\"1Y7-SU-huu\" id=\"VBc-j8-FTI\"/>\n                <outlet property=\"withSecondsCheckbox\" destination=\"gVp-r5-gaa\" id=\"Qnv-xK-lty\"/>\n            </connections>\n            <point key=\"canvasLocation\" x=\"-840\" y=\"219\"/>\n        </customView>\n        <customView id=\"uc4-YQ-4ov\" customClass=\"InfoDateView\" customModule=\"Aerial\" customModuleProvider=\"target\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"580\" height=\"102\"/>\n            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n            <subviews>\n                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"12o-Uw-cyT\">\n                    <rect key=\"frame\" x=\"90\" y=\"70\" width=\"54\" height=\"17\"/>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" alignment=\"right\" title=\"Format:\" id=\"T2G-IG-9XI\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <popUpButton verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"UQm-dH-dhe\">\n                    <rect key=\"frame\" x=\"145\" y=\"57\" width=\"270\" height=\"40\"/>\n                    <popUpButtonCell key=\"cell\" type=\"push\" title=\"Textual (Wednesday, December 25)\" bezelStyle=\"rounded\" alignment=\"left\" controlSize=\"large\" lineBreakMode=\"truncatingTail\" state=\"on\" borderStyle=\"borderAndBezel\" imageScaling=\"proportionallyDown\" inset=\"2\" selectedItem=\"sZW-CJ-giC\" id=\"4is-zP-075\">\n                        <behavior key=\"behavior\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" size=\"14\" name=\"HelveticaNeue\"/>\n                        <menu key=\"menu\" id=\"rrg-td-f3u\">\n                            <items>\n                                <menuItem title=\"Textual (Wednesday, December 25)\" state=\"on\" id=\"sZW-CJ-giC\"/>\n                                <menuItem title=\"Compact (12/25)\" id=\"uDW-mL-pdg\"/>\n                                <menuItem title=\"Custom...\" id=\"sOz-yR-Gco\">\n                                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                </menuItem>\n                            </items>\n                        </menu>\n                    </popUpButtonCell>\n                    <connections>\n                        <action selector=\"dateFormatPopupChange:\" target=\"uc4-YQ-4ov\" id=\"eBZ-8f-9f6\"/>\n                    </connections>\n                </popUpButton>\n                <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"jQV-Kz-kEQ\">\n                    <rect key=\"frame\" x=\"415\" y=\"67.5\" width=\"91\" height=\"22\"/>\n                    <buttonCell key=\"cell\" type=\"check\" title=\"With year\" bezelStyle=\"regularSquare\" imagePosition=\"left\" controlSize=\"large\" state=\"on\" inset=\"2\" id=\"Ta8-2G-fXS\">\n                        <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"withYearCheckboxChange:\" target=\"uc4-YQ-4ov\" id=\"Tgr-yG-ljB\"/>\n                    </connections>\n                </button>\n                <textField focusRingType=\"none\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"6np-uU-8jk\">\n                    <rect key=\"frame\" x=\"150\" y=\"19\" width=\"260\" height=\"22\"/>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" scrollable=\"YES\" lineBreakMode=\"clipping\" selectable=\"YES\" editable=\"YES\" sendsActionOnEndEditing=\"YES\" borderStyle=\"bezel\" placeholderString=\"Unicode format (eg EEEE, MMMM, d)\" drawsBackground=\"YES\" id=\"JRP-5s-tg7\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                    <connections>\n                        <action selector=\"customDateFormatFieldChange:\" target=\"uc4-YQ-4ov\" id=\"D9i-4X-GEO\"/>\n                    </connections>\n                </textField>\n            </subviews>\n            <constraints>\n                <constraint firstItem=\"UQm-dH-dhe\" firstAttribute=\"firstBaseline\" secondItem=\"12o-Uw-cyT\" secondAttribute=\"firstBaseline\" id=\"Al0-A3-Lcy\"/>\n                <constraint firstItem=\"jQV-Kz-kEQ\" firstAttribute=\"leading\" secondItem=\"UQm-dH-dhe\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"Bvh-DJ-r8c\"/>\n                <constraint firstItem=\"UQm-dH-dhe\" firstAttribute=\"top\" secondItem=\"uc4-YQ-4ov\" secondAttribute=\"top\" constant=\"11\" id=\"Kug-T5-bFq\"/>\n                <constraint firstItem=\"6np-uU-8jk\" firstAttribute=\"leading\" secondItem=\"UQm-dH-dhe\" secondAttribute=\"leading\" id=\"L82-a2-bwa\"/>\n                <constraint firstItem=\"UQm-dH-dhe\" firstAttribute=\"leading\" secondItem=\"uc4-YQ-4ov\" secondAttribute=\"leading\" constant=\"150\" id=\"Uwq-vK-IsO\"/>\n                <constraint firstItem=\"6np-uU-8jk\" firstAttribute=\"top\" secondItem=\"UQm-dH-dhe\" secondAttribute=\"bottom\" constant=\"22\" id=\"ji9-ds-IqW\"/>\n                <constraint firstItem=\"UQm-dH-dhe\" firstAttribute=\"leading\" secondItem=\"12o-Uw-cyT\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"kPb-Td-tqc\"/>\n                <constraint firstItem=\"jQV-Kz-kEQ\" firstAttribute=\"firstBaseline\" secondItem=\"UQm-dH-dhe\" secondAttribute=\"firstBaseline\" id=\"whb-k5-f5e\"/>\n                <constraint firstItem=\"6np-uU-8jk\" firstAttribute=\"trailing\" secondItem=\"UQm-dH-dhe\" secondAttribute=\"trailing\" id=\"x79-j0-KqA\"/>\n            </constraints>\n            <connections>\n                <outlet property=\"customDateFormatField\" destination=\"6np-uU-8jk\" id=\"2QG-Qj-IOT\"/>\n                <outlet property=\"dateFormatPopup\" destination=\"UQm-dH-dhe\" id=\"Zfp-6O-GBV\"/>\n                <outlet property=\"withYearCheckbox\" destination=\"jQV-Kz-kEQ\" id=\"ae1-XA-gZS\"/>\n            </connections>\n            <point key=\"canvasLocation\" x=\"-840\" y=\"950\"/>\n        </customView>\n        <customView id=\"cmR-hZ-0Fe\" customClass=\"InfoWeatherView\" customModule=\"Aerial\" customModuleProvider=\"target\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"607\" height=\"238\"/>\n            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n            <subviews>\n                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"MMI-hf-gCZ\">\n                    <rect key=\"frame\" x=\"80\" y=\"106\" width=\"64\" height=\"17\"/>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" alignment=\"right\" title=\"Location:\" id=\"MuN-Fd-8Hd\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <popUpButton verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"mY1-Rf-ATP\">\n                    <rect key=\"frame\" x=\"145\" y=\"93\" width=\"155\" height=\"40\"/>\n                    <popUpButtonCell key=\"cell\" type=\"push\" title=\"Use current\" bezelStyle=\"rounded\" alignment=\"left\" controlSize=\"large\" lineBreakMode=\"truncatingTail\" state=\"on\" borderStyle=\"borderAndBezel\" imageScaling=\"proportionallyDown\" inset=\"2\" selectedItem=\"TyM-g1-qHE\" id=\"79c-Qo-uSx\">\n                        <behavior key=\"behavior\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" size=\"14\" name=\"HelveticaNeue\"/>\n                        <menu key=\"menu\" id=\"p94-Wu-cj3\">\n                            <items>\n                                <menuItem title=\"Use current\" state=\"on\" id=\"TyM-g1-qHE\"/>\n                                <menuItem title=\"Manually specify\" id=\"mwl-wh-ujf\"/>\n                            </items>\n                        </menu>\n                    </popUpButtonCell>\n                    <connections>\n                        <action selector=\"locationModeChange:\" target=\"cmR-hZ-0Fe\" id=\"CAC-b2-I36\"/>\n                    </connections>\n                </popUpButton>\n                <popUpButton verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"WWH-eQ-q01\">\n                    <rect key=\"frame\" x=\"375\" y=\"143\" width=\"66\" height=\"40\"/>\n                    <popUpButtonCell key=\"cell\" type=\"push\" title=\"°C\" bezelStyle=\"rounded\" alignment=\"left\" controlSize=\"large\" lineBreakMode=\"truncatingTail\" state=\"on\" borderStyle=\"borderAndBezel\" imageScaling=\"proportionallyDown\" inset=\"2\" selectedItem=\"kAT-Ix-Epe\" id=\"xKQ-Sj-kNx\">\n                        <behavior key=\"behavior\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" size=\"14\" name=\"HelveticaNeue\"/>\n                        <menu key=\"menu\" id=\"HkF-Pa-9cc\">\n                            <items>\n                                <menuItem title=\"°C\" state=\"on\" id=\"kAT-Ix-Epe\"/>\n                                <menuItem title=\"°F\" id=\"wF9-oz-jZi\"/>\n                            </items>\n                        </menu>\n                    </popUpButtonCell>\n                    <connections>\n                        <action selector=\"degreePopupChange:\" target=\"cmR-hZ-0Fe\" id=\"rGO-hK-OZG\"/>\n                    </connections>\n                </popUpButton>\n                <popUpButton verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"pj2-sU-RdG\">\n                    <rect key=\"frame\" x=\"145\" y=\"143\" width=\"224\" height=\"40\"/>\n                    <popUpButtonCell key=\"cell\" type=\"push\" title=\"Flat symbols (monochrome)\" bezelStyle=\"rounded\" alignment=\"left\" controlSize=\"large\" lineBreakMode=\"truncatingTail\" state=\"on\" borderStyle=\"borderAndBezel\" imageScaling=\"proportionallyDown\" inset=\"2\" selectedItem=\"SlK-mo-emo\" id=\"Vwk-tz-NwH\">\n                        <behavior key=\"behavior\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" size=\"14\" name=\"HelveticaNeue\"/>\n                        <menu key=\"menu\" id=\"YeW-HB-a3b\">\n                            <items>\n                                <menuItem title=\"Flat symbols (monochrome)\" state=\"on\" id=\"SlK-mo-emo\"/>\n                                <menuItem title=\"Flat symbols (multicolor)\" id=\"cFh-rG-ejh\"/>\n                                <menuItem title=\"Color icons (low quality)\" id=\"VID-WC-uqt\"/>\n                            </items>\n                        </menu>\n                    </popUpButtonCell>\n                    <connections>\n                        <action selector=\"iconsChange:\" target=\"cmR-hZ-0Fe\" id=\"ceX-XR-1Ba\"/>\n                    </connections>\n                </popUpButton>\n                <textField focusRingType=\"none\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Iha-a4-YZ0\">\n                    <rect key=\"frame\" x=\"150\" y=\"28\" width=\"250\" height=\"22\"/>\n                    <constraints>\n                        <constraint firstAttribute=\"width\" constant=\"250\" id=\"R0K-YM-KCz\"/>\n                    </constraints>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" scrollable=\"YES\" lineBreakMode=\"clipping\" selectable=\"YES\" editable=\"YES\" sendsActionOnEndEditing=\"YES\" borderStyle=\"bezel\" placeholderString=\"Paris, FR\" drawsBackground=\"YES\" id=\"Qdq-Lo-G62\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                    <connections>\n                        <action selector=\"locationStringChange:\" target=\"cmR-hZ-0Fe\" id=\"2DH-MF-BVO\"/>\n                    </connections>\n                </textField>\n                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"2t2-hO-9s4\">\n                    <rect key=\"frame\" x=\"101\" y=\"156\" width=\"43\" height=\"17\"/>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" alignment=\"right\" title=\"Icons:\" id=\"PAa-nv-nJu\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <button horizontalHuggingPriority=\"750\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"IcH-dE-weS\">\n                    <rect key=\"frame\" x=\"307\" y=\"92\" width=\"35\" height=\"35\"/>\n                    <buttonCell key=\"cell\" type=\"help\" bezelStyle=\"helpButton\" alignment=\"center\" controlSize=\"large\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"3MQ-92-9m9\">\n                        <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"helpWeatherButtonClick:\" target=\"-2\" id=\"UOO-Ut-zBm\"/>\n                    </connections>\n                </button>\n                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"YAo-Tv-Uqc\">\n                    <rect key=\"frame\" x=\"148\" y=\"66\" width=\"60\" height=\"17\"/>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" title=\"Location\" id=\"bJ3-TA-jEX\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"secondaryLabelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Bjs-UA-NkK\">\n                    <rect key=\"frame\" x=\"410\" y=\"17\" width=\"60\" height=\"40\"/>\n                    <buttonCell key=\"cell\" type=\"push\" title=\"Test\" bezelStyle=\"rounded\" alignment=\"center\" controlSize=\"large\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"R2U-fT-M9o\">\n                        <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"testLocationButtonClick:\" target=\"cmR-hZ-0Fe\" id=\"4FO-ev-kS6\"/>\n                    </connections>\n                </button>\n                <popUpButton verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"bc1-t5-1U8\">\n                    <rect key=\"frame\" x=\"145\" y=\"193\" width=\"188\" height=\"40\"/>\n                    <popUpButtonCell key=\"cell\" type=\"push\" title=\"Current weather\" bezelStyle=\"rounded\" alignment=\"left\" controlSize=\"large\" lineBreakMode=\"truncatingTail\" state=\"on\" borderStyle=\"borderAndBezel\" imageScaling=\"proportionallyDown\" inset=\"2\" selectedItem=\"n6w-I3-Hcd\" id=\"RrM-1g-f4Q\">\n                        <behavior key=\"behavior\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" size=\"14\" name=\"HelveticaNeue\"/>\n                        <menu key=\"menu\" id=\"HGB-L7-Fwj\">\n                            <items>\n                                <menuItem title=\"Current weather\" state=\"on\" id=\"n6w-I3-Hcd\"/>\n                                <menuItem title=\"Forecast (next hours)\" id=\"i5W-wv-OE8\"/>\n                                <menuItem title=\"Forecast (next 3 days)\" id=\"ii0-qs-ebA\"/>\n                                <menuItem title=\"Forecast (next 5 days)\" id=\"0gs-le-Djn\">\n                                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                </menuItem>\n                            </items>\n                        </menu>\n                    </popUpButtonCell>\n                    <connections>\n                        <action selector=\"weatherModePopupChange:\" target=\"cmR-hZ-0Fe\" id=\"6uf-Vf-l6Q\"/>\n                    </connections>\n                </popUpButton>\n                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"HYQ-NB-LAH\">\n                    <rect key=\"frame\" x=\"88\" y=\"206\" width=\"56\" height=\"17\"/>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" alignment=\"right\" title=\"Display:\" id=\"tLN-Xk-TM4\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"ebH-Dw-L7o\">\n                    <rect key=\"frame\" x=\"333\" y=\"203.5\" width=\"63\" height=\"22\"/>\n                    <buttonCell key=\"cell\" type=\"check\" title=\"Wind\" bezelStyle=\"regularSquare\" imagePosition=\"left\" controlSize=\"large\" state=\"on\" inset=\"2\" id=\"UkF-Co-r2Q\">\n                        <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"withWindChange:\" target=\"cmR-hZ-0Fe\" id=\"m5Y-IL-uoK\"/>\n                    </connections>\n                </button>\n                <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"AwV-pQ-aIV\">\n                    <rect key=\"frame\" x=\"401\" y=\"203.5\" width=\"87\" height=\"22\"/>\n                    <buttonCell key=\"cell\" type=\"check\" title=\"Humidity\" bezelStyle=\"regularSquare\" imagePosition=\"left\" controlSize=\"large\" state=\"on\" inset=\"2\" id=\"ZMg-9E-Euc\">\n                        <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"withHumidityChange:\" target=\"cmR-hZ-0Fe\" id=\"1VJ-QS-Brf\"/>\n                    </connections>\n                </button>\n                <button translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Mkb-6F-RoA\">\n                    <rect key=\"frame\" x=\"349\" y=\"93\" width=\"90\" height=\"40\"/>\n                    <buttonCell key=\"cell\" type=\"square\" bezelStyle=\"shadowlessSquare\" image=\"openweather_logo\" imagePosition=\"only\" alignment=\"center\" controlSize=\"large\" imageScaling=\"proportionallyUpOrDown\" inset=\"2\" id=\"Yum-qo-4Cz\">\n                        <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\"/>\n                    </buttonCell>\n                    <constraints>\n                        <constraint firstAttribute=\"width\" constant=\"90\" id=\"Jv2-8G-WhZ\"/>\n                        <constraint firstAttribute=\"height\" constant=\"40\" id=\"u2k-2r-QLb\"/>\n                    </constraints>\n                    <connections>\n                        <action selector=\"openWeatherLogoButton:\" target=\"cmR-hZ-0Fe\" id=\"Myl-q4-gGJ\"/>\n                    </connections>\n                </button>\n                <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"RHF-CV-kHu\">\n                    <rect key=\"frame\" x=\"493\" y=\"203.5\" width=\"94\" height=\"22\"/>\n                    <buttonCell key=\"cell\" type=\"check\" title=\"City name\" bezelStyle=\"regularSquare\" imagePosition=\"left\" controlSize=\"large\" state=\"on\" inset=\"2\" id=\"Jpp-uy-v8A\">\n                        <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"withCityChange:\" target=\"cmR-hZ-0Fe\" id=\"qsr-XI-6JN\"/>\n                    </connections>\n                </button>\n                <popUpButton verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"mol-HY-dqc\">\n                    <rect key=\"frame\" x=\"446\" y=\"143\" width=\"82\" height=\"40\"/>\n                    <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                    <popUpButtonCell key=\"cell\" type=\"push\" title=\"km/h\" bezelStyle=\"rounded\" alignment=\"left\" controlSize=\"large\" lineBreakMode=\"truncatingTail\" state=\"on\" borderStyle=\"borderAndBezel\" imageScaling=\"proportionallyDown\" inset=\"2\" selectedItem=\"NiT-9X-V3O\" id=\"SvT-oj-jpi\">\n                        <behavior key=\"behavior\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" size=\"14\" name=\"HelveticaNeue\"/>\n                        <menu key=\"menu\" id=\"ToY-mP-HGD\">\n                            <items>\n                                <menuItem title=\"km/h\" state=\"on\" id=\"NiT-9X-V3O\"/>\n                                <menuItem title=\"m/s\" id=\"ara-s8-6Iv\"/>\n                            </items>\n                        </menu>\n                    </popUpButtonCell>\n                    <connections>\n                        <action selector=\"windModePopupChange:\" target=\"cmR-hZ-0Fe\" id=\"9L4-KH-j8G\"/>\n                    </connections>\n                </popUpButton>\n                <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"bNY-ba-zAN\">\n                    <rect key=\"frame\" x=\"410\" y=\"53\" width=\"60\" height=\"40\"/>\n                    <buttonCell key=\"cell\" type=\"push\" title=\"Test\" bezelStyle=\"rounded\" alignment=\"center\" controlSize=\"large\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"MQl-am-qpj\">\n                        <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"testLocationButtonClick:\" target=\"cmR-hZ-0Fe\" id=\"5tn-aF-cIg\"/>\n                    </connections>\n                </button>\n            </subviews>\n            <constraints>\n                <constraint firstItem=\"pj2-sU-RdG\" firstAttribute=\"leading\" secondItem=\"cmR-hZ-0Fe\" secondAttribute=\"leading\" constant=\"150\" id=\"0Xb-xb-X37\"/>\n                <constraint firstItem=\"RHF-CV-kHu\" firstAttribute=\"firstBaseline\" secondItem=\"AwV-pQ-aIV\" secondAttribute=\"firstBaseline\" id=\"0ke-ET-5TC\"/>\n                <constraint firstAttribute=\"bottom\" secondItem=\"Iha-a4-YZ0\" secondAttribute=\"bottom\" constant=\"28\" id=\"1Cr-Er-TSV\"/>\n                <constraint firstItem=\"Mkb-6F-RoA\" firstAttribute=\"centerY\" secondItem=\"mY1-Rf-ATP\" secondAttribute=\"centerY\" id=\"1ma-7S-i3c\"/>\n                <constraint firstItem=\"RHF-CV-kHu\" firstAttribute=\"leading\" secondItem=\"AwV-pQ-aIV\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"55P-58-zSr\"/>\n                <constraint firstItem=\"bc1-t5-1U8\" firstAttribute=\"firstBaseline\" secondItem=\"HYQ-NB-LAH\" secondAttribute=\"firstBaseline\" id=\"6hW-15-kmK\"/>\n                <constraint firstItem=\"IcH-dE-weS\" firstAttribute=\"centerY\" secondItem=\"mY1-Rf-ATP\" secondAttribute=\"centerY\" id=\"9wu-pE-9qR\"/>\n                <constraint firstItem=\"Bjs-UA-NkK\" firstAttribute=\"leading\" secondItem=\"bNY-ba-zAN\" secondAttribute=\"leading\" id=\"Dda-k4-lAg\"/>\n                <constraint firstItem=\"IcH-dE-weS\" firstAttribute=\"leading\" secondItem=\"mY1-Rf-ATP\" secondAttribute=\"trailing\" constant=\"16\" id=\"KVz-2F-Ywe\"/>\n                <constraint firstItem=\"Bjs-UA-NkK\" firstAttribute=\"firstBaseline\" secondItem=\"Iha-a4-YZ0\" secondAttribute=\"firstBaseline\" id=\"NcH-eI-YXf\"/>\n                <constraint firstItem=\"pj2-sU-RdG\" firstAttribute=\"leading\" secondItem=\"2t2-hO-9s4\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"UoE-Qs-rDe\"/>\n                <constraint firstItem=\"pj2-sU-RdG\" firstAttribute=\"top\" secondItem=\"bc1-t5-1U8\" secondAttribute=\"bottom\" constant=\"22\" id=\"VFg-oP-Sko\"/>\n                <constraint firstItem=\"Iha-a4-YZ0\" firstAttribute=\"leading\" secondItem=\"mY1-Rf-ATP\" secondAttribute=\"leading\" id=\"VpP-3w-IfX\"/>\n                <constraint firstItem=\"pj2-sU-RdG\" firstAttribute=\"firstBaseline\" secondItem=\"2t2-hO-9s4\" secondAttribute=\"firstBaseline\" id=\"W0Z-0G-B4r\"/>\n                <constraint firstItem=\"Iha-a4-YZ0\" firstAttribute=\"top\" secondItem=\"YAo-Tv-Uqc\" secondAttribute=\"bottom\" constant=\"16\" id=\"XoV-EV-HdV\"/>\n                <constraint firstItem=\"WWH-eQ-q01\" firstAttribute=\"leading\" secondItem=\"pj2-sU-RdG\" secondAttribute=\"trailing\" constant=\"16\" id=\"Y0e-TM-gEL\"/>\n                <constraint firstItem=\"bNY-ba-zAN\" firstAttribute=\"firstBaseline\" secondItem=\"YAo-Tv-Uqc\" secondAttribute=\"firstBaseline\" id=\"Y4u-4I-CMb\"/>\n                <constraint firstAttribute=\"trailing\" secondItem=\"RHF-CV-kHu\" secondAttribute=\"trailing\" constant=\"20\" symbolic=\"YES\" id=\"ZTg-EU-eaJ\"/>\n                <constraint firstItem=\"Bjs-UA-NkK\" firstAttribute=\"leading\" secondItem=\"Iha-a4-YZ0\" secondAttribute=\"trailing\" constant=\"16\" id=\"a8B-LT-Hyr\"/>\n                <constraint firstItem=\"WWH-eQ-q01\" firstAttribute=\"firstBaseline\" secondItem=\"2t2-hO-9s4\" secondAttribute=\"firstBaseline\" id=\"ajl-lj-fIR\"/>\n                <constraint firstItem=\"mY1-Rf-ATP\" firstAttribute=\"firstBaseline\" secondItem=\"MMI-hf-gCZ\" secondAttribute=\"firstBaseline\" id=\"b32-yY-EYf\"/>\n                <constraint firstItem=\"bc1-t5-1U8\" firstAttribute=\"leading\" secondItem=\"HYQ-NB-LAH\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"d0e-AZ-pxL\"/>\n                <constraint firstItem=\"YAo-Tv-Uqc\" firstAttribute=\"leading\" secondItem=\"pj2-sU-RdG\" secondAttribute=\"leading\" id=\"dEX-ar-esy\"/>\n                <constraint firstItem=\"bc1-t5-1U8\" firstAttribute=\"top\" secondItem=\"cmR-hZ-0Fe\" secondAttribute=\"top\" constant=\"11\" id=\"goN-cl-mTb\"/>\n                <constraint firstItem=\"mY1-Rf-ATP\" firstAttribute=\"top\" secondItem=\"pj2-sU-RdG\" secondAttribute=\"bottom\" constant=\"22\" id=\"hAF-di-mQj\"/>\n                <constraint firstItem=\"YAo-Tv-Uqc\" firstAttribute=\"top\" secondItem=\"mY1-Rf-ATP\" secondAttribute=\"bottom\" constant=\"16\" id=\"ozH-g8-m6T\"/>\n                <constraint firstItem=\"bc1-t5-1U8\" firstAttribute=\"leading\" secondItem=\"cmR-hZ-0Fe\" secondAttribute=\"leading\" constant=\"150\" id=\"pK0-iw-Xk1\"/>\n                <constraint firstItem=\"ebH-Dw-L7o\" firstAttribute=\"firstBaseline\" secondItem=\"bc1-t5-1U8\" secondAttribute=\"firstBaseline\" id=\"qZ7-Ig-09D\"/>\n                <constraint firstItem=\"mY1-Rf-ATP\" firstAttribute=\"leading\" secondItem=\"MMI-hf-gCZ\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"qnP-7u-9Q2\"/>\n                <constraint firstItem=\"ebH-Dw-L7o\" firstAttribute=\"leading\" secondItem=\"bc1-t5-1U8\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"r5g-X9-8Tk\"/>\n                <constraint firstItem=\"Mkb-6F-RoA\" firstAttribute=\"leading\" secondItem=\"IcH-dE-weS\" secondAttribute=\"trailing\" constant=\"12\" symbolic=\"YES\" id=\"tfz-iW-3de\"/>\n                <constraint firstItem=\"AwV-pQ-aIV\" firstAttribute=\"firstBaseline\" secondItem=\"bc1-t5-1U8\" secondAttribute=\"firstBaseline\" id=\"uA7-mp-p8r\"/>\n                <constraint firstItem=\"AwV-pQ-aIV\" firstAttribute=\"leading\" secondItem=\"ebH-Dw-L7o\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"wOj-jz-TQm\"/>\n                <constraint firstItem=\"mY1-Rf-ATP\" firstAttribute=\"leading\" secondItem=\"pj2-sU-RdG\" secondAttribute=\"leading\" id=\"wRg-i3-SDF\"/>\n            </constraints>\n            <connections>\n                <outlet property=\"degreePopup\" destination=\"WWH-eQ-q01\" id=\"B2k-uQ-E2L\"/>\n                <outlet property=\"iconsPopup\" destination=\"pj2-sU-RdG\" id=\"Emm-SJ-Zub\"/>\n                <outlet property=\"locationLabel\" destination=\"YAo-Tv-Uqc\" id=\"jJh-Rf-hes\"/>\n                <outlet property=\"locationMode\" destination=\"mY1-Rf-ATP\" id=\"cyu-zj-MhQ\"/>\n                <outlet property=\"locationString\" destination=\"Iha-a4-YZ0\" id=\"sPk-Q8-AeX\"/>\n                <outlet property=\"testButtonCity\" destination=\"Bjs-UA-NkK\" id=\"kOw-sj-cIg\"/>\n                <outlet property=\"testButtonLocation\" destination=\"bNY-ba-zAN\" id=\"huz-8U-PYz\"/>\n                <outlet property=\"weatherModePopup\" destination=\"bc1-t5-1U8\" id=\"fdu-1l-38L\"/>\n                <outlet property=\"windModePopup\" destination=\"mol-HY-dqc\" id=\"ayQ-ey-ltt\"/>\n                <outlet property=\"withCity\" destination=\"RHF-CV-kHu\" id=\"LEZ-uQ-BY2\"/>\n                <outlet property=\"withHumidity\" destination=\"AwV-pQ-aIV\" id=\"oVr-Gy-RqA\"/>\n                <outlet property=\"withWind\" destination=\"ebH-Dw-L7o\" id=\"YZW-Ts-hNB\"/>\n            </connections>\n            <point key=\"canvasLocation\" x=\"-112.5\" y=\"1401\"/>\n        </customView>\n        <window title=\"Weather preview\" allowsToolTipsWhenApplicationIsInactive=\"NO\" autorecalculatesKeyViewLoop=\"NO\" hidesOnDeactivate=\"YES\" releasedWhenClosed=\"NO\" visibleAtLaunch=\"NO\" frameAutosaveName=\"\" animationBehavior=\"default\" id=\"T1o-cz-8zC\" customClass=\"NSPanel\">\n            <windowStyleMask key=\"styleMask\" titled=\"YES\" closable=\"YES\" resizable=\"YES\" utility=\"YES\" HUD=\"YES\"/>\n            <windowPositionMask key=\"initialPositionMask\" leftStrut=\"YES\" rightStrut=\"YES\" topStrut=\"YES\" bottomStrut=\"YES\"/>\n            <rect key=\"contentRect\" x=\"272\" y=\"172\" width=\"673\" height=\"487\"/>\n            <rect key=\"screenRect\" x=\"0.0\" y=\"0.0\" width=\"2560\" height=\"1415\"/>\n            <view key=\"contentView\" id=\"Raj-x7-cvl\">\n                <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"673\" height=\"487\"/>\n                <autoresizingMask key=\"autoresizingMask\"/>\n                <subviews>\n                    <customView fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"gfx-ZG-teS\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"177\" width=\"673\" height=\"310\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                    </customView>\n                    <textField focusRingType=\"none\" verticalHuggingPriority=\"750\" horizontalCompressionResistancePriority=\"250\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"3Z6-oE-76I\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"673\" height=\"169\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" flexibleMaxY=\"YES\"/>\n                        <textFieldCell key=\"cell\" selectable=\"YES\" editable=\"YES\" sendsActionOnEndEditing=\"YES\" state=\"on\" borderStyle=\"bezel\" drawsBackground=\"YES\" id=\"7Bu-LI-roc\">\n                            <font key=\"font\" metaFont=\"system\"/>\n                            <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                            <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        </textFieldCell>\n                    </textField>\n                </subviews>\n            </view>\n            <point key=\"canvasLocation\" x=\"894.5\" y=\"-17.5\"/>\n        </window>\n        <customView id=\"go3-Lb-KNk\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"400\" height=\"340\"/>\n            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n            <subviews>\n                <textField focusRingType=\"none\" verticalHuggingPriority=\"750\" horizontalCompressionResistancePriority=\"250\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"sPk-CL-T6p\">\n                    <rect key=\"frame\" x=\"18\" y=\"20\" width=\"364\" height=\"308\"/>\n                    <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                    <textFieldCell key=\"cell\" selectable=\"YES\" id=\"yQd-AC-jyQ\">\n                        <font key=\"font\" metaFont=\"message\" size=\"11\"/>\n                        <string key=\"title\">Aerial uses OpenWeather's API to retrieve and display current conditions and forecasts. In order for this to work, you will need to specify your location. There are two ways to do that:\n\n- Manually specify : Simply enter your location as the name of your city, followed by a country abbreviation. In the United States, to remove ambiguity, you can also add a state abbreviation  (e.g. Cupertino, CA, US).\n\n- Use current location : For this to work, Aerial will ask your mac for your current location, which is provided by macOS location services. This information is then sent to OpenWeather's API to retrieve conditions to the city closest to the location specified. \n\nFor privacy reasons, the coordinates of your location are rounded to two decimals, leaving a precision of about 1 km. Please note that you will need to allow Aerial to use location services for this to work. In macOS Big Sur, please navigate to System Preferences &gt; Security &amp; Privacy &gt; Privacy &gt; Location Services and enable \"legacyScreenSaver\"\n\nIndependant of your choice, you can preview the results using the \"Test\" button below. </string>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n            </subviews>\n            <point key=\"canvasLocation\" x=\"426\" y=\"-585\"/>\n        </customView>\n        <customView id=\"OyK-gu-5yP\" userLabel=\"Clock Extra View\" customClass=\"InfoClockView\" customModule=\"Aerial\" customModuleProvider=\"target\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"580\" height=\"131\"/>\n            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n            <subviews>\n                <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"q9j-r0-6Oe\">\n                    <rect key=\"frame\" x=\"147\" y=\"100.5\" width=\"117\" height=\"22\"/>\n                    <buttonCell key=\"cell\" type=\"check\" title=\"With seconds\" bezelStyle=\"regularSquare\" imagePosition=\"left\" controlSize=\"large\" state=\"on\" inset=\"2\" id=\"lJR-jf-K6g\">\n                        <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"secondsClick:\" target=\"OyK-gu-5yP\" id=\"CeD-r7-iEA\"/>\n                    </connections>\n                </button>\n                <popUpButton verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"sMh-8c-gCl\">\n                    <rect key=\"frame\" x=\"145\" y=\"47\" width=\"111\" height=\"40\"/>\n                    <popUpButtonCell key=\"cell\" type=\"push\" title=\"Default\" bezelStyle=\"rounded\" alignment=\"left\" controlSize=\"large\" lineBreakMode=\"truncatingTail\" state=\"on\" borderStyle=\"borderAndBezel\" imageScaling=\"proportionallyDown\" inset=\"2\" selectedItem=\"uaE-4p-KWC\" id=\"gOW-Cb-Vbq\">\n                        <behavior key=\"behavior\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" size=\"14\" name=\"HelveticaNeue\"/>\n                        <menu key=\"menu\" id=\"VD2-q9-u8Q\">\n                            <items>\n                                <menuItem title=\"Default\" state=\"on\" id=\"uaE-4p-KWC\"/>\n                                <menuItem title=\"24 hours\" id=\"R5b-Lg-1SE\"/>\n                                <menuItem title=\"12 hours\" id=\"ADR-DQ-Ujh\"/>\n                                <menuItem title=\"Custom...\" id=\"Xgh-Od-wWE\">\n                                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                </menuItem>\n                            </items>\n                        </menu>\n                    </popUpButtonCell>\n                    <connections>\n                        <action selector=\"clockFormatChange:\" target=\"OyK-gu-5yP\" id=\"h1Q-Ia-Ij2\"/>\n                    </connections>\n                </popUpButton>\n                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"wrp-j1-frU\">\n                    <rect key=\"frame\" x=\"90\" y=\"60\" width=\"54\" height=\"17\"/>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" alignment=\"right\" title=\"Format:\" id=\"HfW-zW-MAZ\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <textField focusRingType=\"none\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"2fJ-Nq-rVX\">\n                    <rect key=\"frame\" x=\"150\" y=\"9\" width=\"250\" height=\"22\"/>\n                    <constraints>\n                        <constraint firstAttribute=\"width\" constant=\"250\" id=\"fnW-Hi-o1g\"/>\n                    </constraints>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" scrollable=\"YES\" lineBreakMode=\"clipping\" selectable=\"YES\" editable=\"YES\" sendsActionOnEndEditing=\"YES\" borderStyle=\"bezel\" placeholderString=\"Unicode format (eg h : mm)\" drawsBackground=\"YES\" id=\"FGl-h1-aNM\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                    <connections>\n                        <action selector=\"customTimeFormatFieldChange:\" target=\"OyK-gu-5yP\" id=\"Efu-xx-rjm\"/>\n                    </connections>\n                </textField>\n                <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"hRK-bh-FN7\">\n                    <rect key=\"frame\" x=\"256\" y=\"57.5\" width=\"109\" height=\"22\"/>\n                    <buttonCell key=\"cell\" type=\"check\" title=\"Hide AM/PM\" bezelStyle=\"regularSquare\" imagePosition=\"left\" controlSize=\"large\" state=\"on\" inset=\"2\" id=\"FLS-1J-0NL\">\n                        <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"hideAmPmCheckboxClick:\" target=\"OyK-gu-5yP\" id=\"euV-MY-4pe\"/>\n                    </connections>\n                </button>\n            </subviews>\n            <constraints>\n                <constraint firstItem=\"2fJ-Nq-rVX\" firstAttribute=\"leading\" secondItem=\"sMh-8c-gCl\" secondAttribute=\"leading\" id=\"2IA-mX-fkJ\"/>\n                <constraint firstItem=\"hRK-bh-FN7\" firstAttribute=\"firstBaseline\" secondItem=\"sMh-8c-gCl\" secondAttribute=\"firstBaseline\" id=\"3Br-zA-NVe\"/>\n                <constraint firstItem=\"sMh-8c-gCl\" firstAttribute=\"top\" secondItem=\"q9j-r0-6Oe\" secondAttribute=\"bottom\" constant=\"22\" id=\"49g-bt-wBI\"/>\n                <constraint firstItem=\"q9j-r0-6Oe\" firstAttribute=\"top\" secondItem=\"OyK-gu-5yP\" secondAttribute=\"top\" constant=\"11\" id=\"HF8-kJ-TKF\"/>\n                <constraint firstItem=\"hRK-bh-FN7\" firstAttribute=\"leading\" secondItem=\"sMh-8c-gCl\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"OSw-t3-M5p\"/>\n                <constraint firstItem=\"sMh-8c-gCl\" firstAttribute=\"leading\" secondItem=\"wrp-j1-frU\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"UBK-LH-SSY\"/>\n                <constraint firstItem=\"2fJ-Nq-rVX\" firstAttribute=\"top\" secondItem=\"sMh-8c-gCl\" secondAttribute=\"bottom\" constant=\"22\" id=\"b9j-Fb-OAx\"/>\n                <constraint firstItem=\"sMh-8c-gCl\" firstAttribute=\"firstBaseline\" secondItem=\"wrp-j1-frU\" secondAttribute=\"firstBaseline\" id=\"kEz-lm-caw\"/>\n                <constraint firstItem=\"sMh-8c-gCl\" firstAttribute=\"leading\" secondItem=\"OyK-gu-5yP\" secondAttribute=\"leading\" constant=\"150\" id=\"lka-S1-NLP\"/>\n                <constraint firstItem=\"q9j-r0-6Oe\" firstAttribute=\"leading\" secondItem=\"OyK-gu-5yP\" secondAttribute=\"leading\" constant=\"150\" id=\"zdF-CI-wo7\"/>\n            </constraints>\n            <connections>\n                <outlet property=\"clockFormat\" destination=\"sMh-8c-gCl\" id=\"m5j-cy-Agx\"/>\n                <outlet property=\"customTimeFormatField\" destination=\"2fJ-Nq-rVX\" id=\"F4L-wq-MqK\"/>\n                <outlet property=\"hideAmPmCheckbox\" destination=\"hRK-bh-FN7\" id=\"35F-a5-e7j\"/>\n                <outlet property=\"secondsCheckbox\" destination=\"q9j-r0-6Oe\" id=\"wqu-S1-GTH\"/>\n            </connections>\n            <point key=\"canvasLocation\" x=\"-840\" y=\"546.5\"/>\n        </customView>\n        <customView id=\"OhT-fX-ti2\" userLabel=\"Countdown Extra View\" customClass=\"InfoCountdownView\" customModule=\"Aerial\" customModuleProvider=\"target\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"580\" height=\"131\"/>\n            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n            <subviews>\n                <datePicker verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"VqT-6u-vi8\">\n                    <rect key=\"frame\" x=\"150\" y=\"52\" width=\"151\" height=\"22\"/>\n                    <datePickerCell key=\"cell\" controlSize=\"large\" borderStyle=\"bezel\" alignment=\"left\" id=\"SqO-Mg-AO0\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <date key=\"date\" timeIntervalSinceReferenceDate=\"616845641.97237301\">\n                            <!--2020-07-19 10:00:41 +0000-->\n                        </date>\n                        <color key=\"backgroundColor\" name=\"controlBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <datePickerElements key=\"datePickerElements\" year=\"YES\" month=\"YES\" day=\"YES\" hour=\"YES\" minute=\"YES\" second=\"YES\"/>\n                    </datePickerCell>\n                    <connections>\n                        <action selector=\"targetTimeDatePickerChange:\" target=\"OhT-fX-ti2\" id=\"IzI-s0-izj\"/>\n                    </connections>\n                </datePicker>\n                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"gBD-Sg-YER\">\n                    <rect key=\"frame\" x=\"45\" y=\"99\" width=\"99\" height=\"17\"/>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" alignment=\"right\" title=\"Countdown to:\" id=\"spm-K8-eq5\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <popUpButton verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"vu6-dz-LFW\">\n                    <rect key=\"frame\" x=\"145\" y=\"86\" width=\"128\" height=\"40\"/>\n                    <popUpButtonCell key=\"cell\" type=\"push\" title=\"Precise date\" bezelStyle=\"rounded\" alignment=\"left\" controlSize=\"large\" lineBreakMode=\"truncatingTail\" state=\"on\" borderStyle=\"borderAndBezel\" imageScaling=\"proportionallyDown\" inset=\"2\" selectedItem=\"Arb-DT-w5t\" id=\"BkG-UK-VNV\">\n                        <behavior key=\"behavior\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" size=\"14\" name=\"HelveticaNeue\"/>\n                        <menu key=\"menu\" id=\"9Rh-Ry-bm3\">\n                            <items>\n                                <menuItem title=\"Precise date\" state=\"on\" id=\"Arb-DT-w5t\"/>\n                                <menuItem title=\"Time of day\" id=\"65s-H5-d1b\"/>\n                            </items>\n                        </menu>\n                    </popUpButtonCell>\n                    <connections>\n                        <action selector=\"timeModePopupChange:\" target=\"OhT-fX-ti2\" id=\"v1Q-7X-GSu\"/>\n                    </connections>\n                </popUpButton>\n                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"For-Kd-aqi\">\n                    <rect key=\"frame\" x=\"63\" y=\"56\" width=\"81\" height=\"17\"/>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" alignment=\"right\" title=\"Target time:\" id=\"09d-aS-YnK\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"cm5-HA-hKl\">\n                    <rect key=\"frame\" x=\"281\" y=\"96.5\" width=\"117\" height=\"22\"/>\n                    <buttonCell key=\"cell\" type=\"check\" title=\"With seconds\" bezelStyle=\"regularSquare\" imagePosition=\"left\" controlSize=\"large\" state=\"on\" inset=\"2\" id=\"oVs-Ii-qMe\">\n                        <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"withSecondsCheckboxClick:\" target=\"OhT-fX-ti2\" id=\"YGo-t0-jdT\"/>\n                    </connections>\n                </button>\n                <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"2A5-7P-mvL\">\n                    <rect key=\"frame\" x=\"147\" y=\"10.5\" width=\"135\" height=\"22\"/>\n                    <buttonCell key=\"cell\" type=\"check\" title=\"Only show after \" bezelStyle=\"regularSquare\" imagePosition=\"left\" controlSize=\"large\" state=\"on\" inset=\"2\" id=\"JRz-Os-UZb\">\n                        <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"limitToIntervalClick:\" target=\"OhT-fX-ti2\" id=\"b8N-hE-Bw1\"/>\n                    </connections>\n                </button>\n                <datePicker verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"VCk-nf-BTu\">\n                    <rect key=\"frame\" x=\"290\" y=\"9\" width=\"151\" height=\"22\"/>\n                    <datePickerCell key=\"cell\" controlSize=\"large\" borderStyle=\"bezel\" alignment=\"left\" id=\"d1w-rW-mhy\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <date key=\"date\" timeIntervalSinceReferenceDate=\"616845641.97390699\">\n                            <!--2020-07-19 10:00:41 +0000-->\n                        </date>\n                        <color key=\"backgroundColor\" name=\"controlBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <datePickerElements key=\"datePickerElements\" year=\"YES\" month=\"YES\" day=\"YES\" hour=\"YES\" minute=\"YES\" second=\"YES\"/>\n                    </datePickerCell>\n                    <connections>\n                        <action selector=\"limitIntervalDatePickerChange:\" target=\"OhT-fX-ti2\" id=\"4MZ-XU-ztB\"/>\n                    </connections>\n                </datePicker>\n            </subviews>\n            <constraints>\n                <constraint firstItem=\"VCk-nf-BTu\" firstAttribute=\"firstBaseline\" secondItem=\"2A5-7P-mvL\" secondAttribute=\"firstBaseline\" id=\"300-Fy-saB\"/>\n                <constraint firstItem=\"VqT-6u-vi8\" firstAttribute=\"leading\" secondItem=\"OhT-fX-ti2\" secondAttribute=\"leading\" constant=\"150\" id=\"GDc-Of-UFY\"/>\n                <constraint firstItem=\"VqT-6u-vi8\" firstAttribute=\"top\" secondItem=\"vu6-dz-LFW\" secondAttribute=\"bottom\" constant=\"22\" id=\"LeS-k5-FRW\"/>\n                <constraint firstItem=\"VCk-nf-BTu\" firstAttribute=\"leading\" secondItem=\"2A5-7P-mvL\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"MSB-K8-bqC\"/>\n                <constraint firstItem=\"vu6-dz-LFW\" firstAttribute=\"firstBaseline\" secondItem=\"gBD-Sg-YER\" secondAttribute=\"firstBaseline\" id=\"V4R-mZ-ihk\"/>\n                <constraint firstItem=\"cm5-HA-hKl\" firstAttribute=\"firstBaseline\" secondItem=\"gBD-Sg-YER\" secondAttribute=\"firstBaseline\" id=\"VJH-lL-bEB\"/>\n                <constraint firstItem=\"2A5-7P-mvL\" firstAttribute=\"leading\" secondItem=\"OhT-fX-ti2\" secondAttribute=\"leading\" constant=\"150\" id=\"XDI-zd-PTb\"/>\n                <constraint firstItem=\"vu6-dz-LFW\" firstAttribute=\"top\" secondItem=\"OhT-fX-ti2\" secondAttribute=\"top\" constant=\"11\" id=\"XW3-ad-Hp2\"/>\n                <constraint firstItem=\"cm5-HA-hKl\" firstAttribute=\"leading\" secondItem=\"vu6-dz-LFW\" secondAttribute=\"trailing\" constant=\"16\" id=\"a9U-Jl-cc5\"/>\n                <constraint firstItem=\"2A5-7P-mvL\" firstAttribute=\"top\" secondItem=\"VqT-6u-vi8\" secondAttribute=\"bottom\" constant=\"22\" id=\"eTW-XJ-GWw\"/>\n                <constraint firstItem=\"vu6-dz-LFW\" firstAttribute=\"leading\" secondItem=\"OhT-fX-ti2\" secondAttribute=\"leading\" constant=\"150\" id=\"n67-xe-Nnm\"/>\n                <constraint firstItem=\"VqT-6u-vi8\" firstAttribute=\"firstBaseline\" secondItem=\"For-Kd-aqi\" secondAttribute=\"firstBaseline\" id=\"yP3-1o-8Ex\"/>\n                <constraint firstItem=\"vu6-dz-LFW\" firstAttribute=\"leading\" secondItem=\"gBD-Sg-YER\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"yuM-FL-FfH\"/>\n                <constraint firstItem=\"VqT-6u-vi8\" firstAttribute=\"leading\" secondItem=\"For-Kd-aqi\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"ywv-hD-fY7\"/>\n            </constraints>\n            <connections>\n                <outlet property=\"limitIntervalDatePicker\" destination=\"VCk-nf-BTu\" id=\"GnB-2N-vqa\"/>\n                <outlet property=\"limitToIntervalCheckbox\" destination=\"2A5-7P-mvL\" id=\"jyA-oV-b97\"/>\n                <outlet property=\"targetTimeDatePicker\" destination=\"VqT-6u-vi8\" id=\"sH7-Gn-oMv\"/>\n                <outlet property=\"timeModePopup\" destination=\"vu6-dz-LFW\" id=\"dhQ-Jo-LpN\"/>\n                <outlet property=\"withSecondsCheckbox\" destination=\"cm5-HA-hKl\" id=\"wpz-5P-IRg\"/>\n            </connections>\n            <point key=\"canvasLocation\" x=\"-840\" y=\"7.5\"/>\n        </customView>\n        <customView id=\"eaZ-HA-6Kx\" userLabel=\"Message Text View\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"580\" height=\"139\"/>\n            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n            <subviews>\n                <scrollView borderType=\"none\" horizontalLineScroll=\"10\" horizontalPageScroll=\"10\" verticalLineScroll=\"10\" verticalPageScroll=\"10\" hasHorizontalScroller=\"NO\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"2vn-TO-wUI\">\n                    <rect key=\"frame\" x=\"150\" y=\"20\" width=\"410\" height=\"108\"/>\n                    <clipView key=\"contentView\" drawsBackground=\"NO\" id=\"Ax6-3Y-Vnl\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"410\" height=\"108\"/>\n                        <autoresizingMask key=\"autoresizingMask\"/>\n                        <subviews>\n                            <textView importsGraphics=\"NO\" richText=\"NO\" verticallyResizable=\"YES\" smartInsertDelete=\"YES\" id=\"ehG-nq-Wse\">\n                                <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"410\" height=\"108\"/>\n                                <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                                <color key=\"textColor\" name=\"textColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                <size key=\"minSize\" width=\"410\" height=\"108\"/>\n                                <size key=\"maxSize\" width=\"420\" height=\"10000000\"/>\n                                <color key=\"insertionPointColor\" name=\"textColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                            </textView>\n                        </subviews>\n                    </clipView>\n                    <constraints>\n                        <constraint firstAttribute=\"width\" constant=\"410\" id=\"Een-XC-5iw\"/>\n                        <constraint firstAttribute=\"height\" constant=\"108\" id=\"VFm-js-ere\"/>\n                    </constraints>\n                    <scroller key=\"horizontalScroller\" hidden=\"YES\" wantsLayer=\"YES\" verticalHuggingPriority=\"750\" horizontal=\"YES\" id=\"slf-6d-QJ7\">\n                        <rect key=\"frame\" x=\"-100\" y=\"-100\" width=\"240\" height=\"16\"/>\n                        <autoresizingMask key=\"autoresizingMask\"/>\n                    </scroller>\n                    <scroller key=\"verticalScroller\" wantsLayer=\"YES\" verticalHuggingPriority=\"750\" horizontal=\"NO\" id=\"lvD-6u-5me\">\n                        <rect key=\"frame\" x=\"394\" y=\"0.0\" width=\"16\" height=\"108\"/>\n                        <autoresizingMask key=\"autoresizingMask\"/>\n                    </scroller>\n                </scrollView>\n                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"VRB-LU-QAK\">\n                    <rect key=\"frame\" x=\"78\" y=\"109\" width=\"66\" height=\"17\"/>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" alignment=\"right\" title=\"Message:\" id=\"lPh-y5-xXN\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n            </subviews>\n            <constraints>\n                <constraint firstItem=\"2vn-TO-wUI\" firstAttribute=\"leading\" secondItem=\"eaZ-HA-6Kx\" secondAttribute=\"leading\" constant=\"150\" id=\"Zyr-ZZ-Lmd\"/>\n                <constraint firstItem=\"2vn-TO-wUI\" firstAttribute=\"leading\" secondItem=\"VRB-LU-QAK\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"oZW-7b-tSr\"/>\n                <constraint firstItem=\"VRB-LU-QAK\" firstAttribute=\"top\" secondItem=\"eaZ-HA-6Kx\" secondAttribute=\"top\" constant=\"13\" id=\"sVN-4k-BED\"/>\n                <constraint firstItem=\"2vn-TO-wUI\" firstAttribute=\"top\" secondItem=\"eaZ-HA-6Kx\" secondAttribute=\"top\" constant=\"11\" id=\"wps-8E-RLL\"/>\n            </constraints>\n            <point key=\"canvasLocation\" x=\"-161\" y=\"-404.5\"/>\n        </customView>\n        <customView id=\"bXW-hw-1fP\" userLabel=\"Message Shell View\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"580\" height=\"225\"/>\n            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n            <subviews>\n                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Lrt-Xz-kJn\">\n                    <rect key=\"frame\" x=\"64\" y=\"194\" width=\"80\" height=\"17\"/>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" alignment=\"right\" title=\"Shell script:\" id=\"X4U-sg-Jpi\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <textField focusRingType=\"none\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"mQk-nn-Wxa\">\n                    <rect key=\"frame\" x=\"150\" y=\"192\" width=\"330\" height=\"22\"/>\n                    <constraints>\n                        <constraint firstAttribute=\"width\" constant=\"330\" id=\"ZnG-81-TuS\"/>\n                    </constraints>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" scrollable=\"YES\" lineBreakMode=\"clipping\" selectable=\"YES\" editable=\"YES\" sendsActionOnEndEditing=\"YES\" borderStyle=\"bezel\" placeholderString=\"Type your script location (eg : /Users/Shared/test.sh)\" drawsBackground=\"YES\" id=\"VA7-0j-0Eq\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                    <connections>\n                        <action selector=\"shellScriptChange:\" target=\"wFi-1P-F0m\" id=\"2pM-pU-Vyw\"/>\n                    </connections>\n                </textField>\n                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Ef6-UR-u2G\">\n                    <rect key=\"frame\" x=\"148\" y=\"155\" width=\"414\" height=\"30\"/>\n                    <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" title=\"Your script must be on your main drive and not be in a priviledged location (Documents, Desktop, Downloads, etc...).\" id=\"LF8-NS-AiD\">\n                        <font key=\"font\" metaFont=\"cellTitle\"/>\n                        <color key=\"textColor\" name=\"secondaryLabelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"7LK-MG-r8x\">\n                    <rect key=\"frame\" x=\"482\" y=\"181\" width=\"60\" height=\"40\"/>\n                    <buttonCell key=\"cell\" type=\"push\" title=\"Test\" bezelStyle=\"rounded\" alignment=\"center\" controlSize=\"large\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"1gz-ev-zXn\">\n                        <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"shellScriptTestClick:\" target=\"wFi-1P-F0m\" id=\"z73-iN-VMf\"/>\n                    </connections>\n                </button>\n                <textField focusRingType=\"none\" verticalHuggingPriority=\"750\" horizontalCompressionResistancePriority=\"250\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"ZIt-5C-mn7\">\n                    <rect key=\"frame\" x=\"148\" y=\"18\" width=\"412\" height=\"83\"/>\n                    <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" selectable=\"YES\" title=\"Multiline Label\" id=\"JMD-Xw-Lba\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <popUpButton verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Ev7-MY-EGf\">\n                    <rect key=\"frame\" x=\"145\" y=\"109\" width=\"134\" height=\"40\"/>\n                    <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                    <popUpButtonCell key=\"cell\" type=\"push\" title=\"Never\" bezelStyle=\"rounded\" alignment=\"left\" controlSize=\"large\" lineBreakMode=\"truncatingTail\" state=\"on\" borderStyle=\"borderAndBezel\" imageScaling=\"proportionallyDown\" inset=\"2\" selectedItem=\"Ik1-ho-eWp\" id=\"npc-Ft-VrB\">\n                        <behavior key=\"behavior\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" size=\"14\" name=\"HelveticaNeue\"/>\n                        <menu key=\"menu\" id=\"wYJ-Uc-1IP\">\n                            <items>\n                                <menuItem title=\"Never\" state=\"on\" id=\"Ik1-ho-eWp\"/>\n                                <menuItem title=\"10 seconds\" id=\"eJH-Hs-aC6\"/>\n                                <menuItem title=\"30 seconds\" id=\"z9m-Vt-o2f\"/>\n                                <menuItem title=\"1 minute\" id=\"V43-Vb-Szp\"/>\n                                <menuItem title=\"5 minutes\" id=\"fWW-7E-I3C\"/>\n                                <menuItem title=\"10 minutes\" id=\"VNx-C8-9Ic\"/>\n                            </items>\n                        </menu>\n                    </popUpButtonCell>\n                    <connections>\n                        <action selector=\"shellRefreshPeriodicityChange:\" target=\"wFi-1P-F0m\" id=\"4Y0-hp-fLR\"/>\n                    </connections>\n                </popUpButton>\n                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"IZw-Oc-MiR\">\n                    <rect key=\"frame\" x=\"47\" y=\"122\" width=\"97\" height=\"17\"/>\n                    <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" alignment=\"right\" title=\"Refresh every:\" id=\"ueo-cn-Kwt\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n            </subviews>\n            <constraints>\n                <constraint firstItem=\"mQk-nn-Wxa\" firstAttribute=\"leading\" secondItem=\"bXW-hw-1fP\" secondAttribute=\"leading\" constant=\"150\" id=\"AKH-QP-SJl\"/>\n                <constraint firstItem=\"mQk-nn-Wxa\" firstAttribute=\"top\" secondItem=\"bXW-hw-1fP\" secondAttribute=\"top\" constant=\"11\" id=\"EFC-Qb-1eS\"/>\n                <constraint firstItem=\"mQk-nn-Wxa\" firstAttribute=\"firstBaseline\" secondItem=\"Lrt-Xz-kJn\" secondAttribute=\"firstBaseline\" id=\"Ksj-FC-Efv\"/>\n                <constraint firstItem=\"7LK-MG-r8x\" firstAttribute=\"leading\" secondItem=\"mQk-nn-Wxa\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"Mcf-wY-Ew9\"/>\n                <constraint firstItem=\"7LK-MG-r8x\" firstAttribute=\"firstBaseline\" secondItem=\"mQk-nn-Wxa\" secondAttribute=\"firstBaseline\" id=\"QNZ-bW-Sv3\"/>\n                <constraint firstItem=\"mQk-nn-Wxa\" firstAttribute=\"leading\" secondItem=\"Lrt-Xz-kJn\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"p7r-5c-eGP\"/>\n            </constraints>\n            <point key=\"canvasLocation\" x=\"-161\" y=\"-118.5\"/>\n        </customView>\n        <customView id=\"T8p-iy-4mZ\" userLabel=\"Common Info View\" customClass=\"InfoCommonView\" customModule=\"Aerial\" customModuleProvider=\"target\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"595\" height=\"273\"/>\n            <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" flexibleMinY=\"YES\"/>\n            <subviews>\n                <button toolTip=\"Enable or disable this overlay\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"fYk-Ks-9Iw\">\n                    <rect key=\"frame\" x=\"147\" y=\"231.5\" width=\"73\" height=\"22\"/>\n                    <buttonCell key=\"cell\" type=\"check\" title=\"Enable\" bezelStyle=\"regularSquare\" imagePosition=\"left\" controlSize=\"large\" state=\"on\" inset=\"2\" id=\"7jg-Fa-pIh\">\n                        <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"enabledClick:\" target=\"T8p-iy-4mZ\" id=\"OFs-nA-Ui4\"/>\n                    </connections>\n                </button>\n                <imageView horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"7Wo-dF-cCr\">\n                    <rect key=\"frame\" x=\"150\" y=\"113\" width=\"174\" height=\"99\"/>\n                    <constraints>\n                        <constraint firstAttribute=\"width\" constant=\"174\" id=\"CMd-el-Jpl\"/>\n                        <constraint firstAttribute=\"height\" constant=\"99\" id=\"xhi-ya-NxN\"/>\n                    </constraints>\n                    <imageCell key=\"cell\" controlSize=\"large\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" image=\"screen0\" id=\"OVf-av-sk6\"/>\n                </imageView>\n                <button toolTip=\"Top left corner\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"hFM-UZ-T70\">\n                    <rect key=\"frame\" x=\"155\" y=\"187\" width=\"22\" height=\"22\"/>\n                    <buttonCell key=\"cell\" type=\"radio\" bezelStyle=\"regularSquare\" imagePosition=\"left\" alignment=\"left\" controlSize=\"large\" inset=\"2\" id=\"Q10-oK-WD4\">\n                        <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"changePosition:\" target=\"T8p-iy-4mZ\" id=\"e4h-sA-NKL\"/>\n                    </connections>\n                </button>\n                <button toolTip=\"Top right corner\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"HXi-fo-A8E\">\n                    <rect key=\"frame\" x=\"297\" y=\"187\" width=\"22\" height=\"22\"/>\n                    <buttonCell key=\"cell\" type=\"radio\" bezelStyle=\"regularSquare\" imagePosition=\"left\" alignment=\"left\" controlSize=\"large\" inset=\"2\" id=\"jT5-Q2-aPx\">\n                        <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"changePosition:\" target=\"T8p-iy-4mZ\" id=\"SRV-QN-vPF\"/>\n                    </connections>\n                </button>\n                <button toolTip=\"Bottom right corner\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"lBk-NQ-Rjz\">\n                    <rect key=\"frame\" x=\"297\" y=\"117\" width=\"22\" height=\"22\"/>\n                    <buttonCell key=\"cell\" type=\"radio\" bezelStyle=\"regularSquare\" imagePosition=\"left\" alignment=\"left\" controlSize=\"large\" inset=\"2\" id=\"BN5-sT-gqF\">\n                        <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"changePosition:\" target=\"T8p-iy-4mZ\" id=\"sJB-Od-vtu\"/>\n                    </connections>\n                </button>\n                <button toolTip=\"Centre\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"CgG-gW-q2H\">\n                    <rect key=\"frame\" x=\"226\" y=\"152\" width=\"22\" height=\"22\"/>\n                    <buttonCell key=\"cell\" type=\"radio\" bezelStyle=\"regularSquare\" imagePosition=\"left\" alignment=\"left\" controlSize=\"large\" inset=\"2\" id=\"iG4-nz-hmf\">\n                        <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"changePosition:\" target=\"T8p-iy-4mZ\" id=\"baZ-FB-YlA\"/>\n                    </connections>\n                </button>\n                <button toolTip=\"Bottom left corner\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"1l4-Hf-IvH\">\n                    <rect key=\"frame\" x=\"155\" y=\"117\" width=\"22\" height=\"22\"/>\n                    <buttonCell key=\"cell\" type=\"radio\" bezelStyle=\"regularSquare\" imagePosition=\"left\" alignment=\"left\" controlSize=\"large\" inset=\"2\" id=\"pFe-vt-1nc\">\n                        <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"changePosition:\" target=\"T8p-iy-4mZ\" id=\"pID-LI-Jhf\"/>\n                    </connections>\n                </button>\n                <button toolTip=\"Top middle edge\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"VAs-nn-glQ\">\n                    <rect key=\"frame\" x=\"226\" y=\"187\" width=\"22\" height=\"22\"/>\n                    <buttonCell key=\"cell\" type=\"radio\" bezelStyle=\"regularSquare\" imagePosition=\"left\" alignment=\"left\" controlSize=\"large\" inset=\"2\" id=\"9Fn-Mn-t6E\">\n                        <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"changePosition:\" target=\"T8p-iy-4mZ\" id=\"kaF-8y-k7f\"/>\n                    </connections>\n                </button>\n                <button toolTip=\"Bottom middle edge\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"42k-s1-y00\">\n                    <rect key=\"frame\" x=\"226\" y=\"117\" width=\"22\" height=\"22\"/>\n                    <buttonCell key=\"cell\" type=\"radio\" bezelStyle=\"regularSquare\" imagePosition=\"left\" alignment=\"left\" controlSize=\"large\" inset=\"2\" id=\"Lwh-7R-egT\">\n                        <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"changePosition:\" target=\"T8p-iy-4mZ\" id=\"nQE-RP-bFE\"/>\n                    </connections>\n                </button>\n                <button toolTip=\"Random corner\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Egt-BD-zPe\">\n                    <rect key=\"frame\" x=\"343\" y=\"184.5\" width=\"129\" height=\"22\"/>\n                    <buttonCell key=\"cell\" type=\"radio\" title=\"Random corner\" bezelStyle=\"regularSquare\" imagePosition=\"left\" alignment=\"left\" controlSize=\"large\" inset=\"2\" id=\"eXP-MW-gDP\">\n                        <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"changePosition:\" target=\"T8p-iy-4mZ\" id=\"J0w-ZU-lbJ\"/>\n                    </connections>\n                </button>\n                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"uHM-CZ-kI1\">\n                    <rect key=\"frame\" x=\"84\" y=\"195\" width=\"60\" height=\"17\"/>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" alignment=\"right\" title=\"Position:\" id=\"AfN-7a-1XZ\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"jbv-Al-Uls\">\n                    <rect key=\"frame\" x=\"81\" y=\"70\" width=\"63\" height=\"17\"/>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" alignment=\"right\" title=\"Displays:\" id=\"YYY-xm-VoW\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <popUpButton toolTip=\"On which display(s) should the overlay appear?\" verticalHuggingPriority=\"749\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"5jY-MV-o3B\">\n                    <rect key=\"frame\" x=\"145\" y=\"57\" width=\"180\" height=\"40\"/>\n                    <popUpButtonCell key=\"cell\" type=\"push\" title=\"All displays\" bezelStyle=\"rounded\" alignment=\"left\" controlSize=\"large\" lineBreakMode=\"truncatingTail\" state=\"on\" borderStyle=\"borderAndBezel\" imageScaling=\"proportionallyDown\" inset=\"2\" selectedItem=\"T10-2N-R55\" id=\"klE-bV-ZQx\">\n                        <behavior key=\"behavior\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" size=\"14\" name=\"HelveticaNeue\"/>\n                        <menu key=\"menu\" id=\"ReA-OA-GIJ\">\n                            <items>\n                                <menuItem title=\"All displays\" state=\"on\" id=\"T10-2N-R55\"/>\n                                <menuItem title=\"Main display\" id=\"uLF-ul-R1u\">\n                                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                </menuItem>\n                                <menuItem title=\"Secondary display(s)\" id=\"Ahx-GK-eXP\">\n                                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                </menuItem>\n                            </items>\n                        </menu>\n                    </popUpButtonCell>\n                    <connections>\n                        <action selector=\"changeDisplays:\" target=\"T8p-iy-4mZ\" id=\"Lmk-f5-Wau\"/>\n                    </connections>\n                </popUpButton>\n                <button toolTip=\"Reset font to default\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"JnO-I8-Uqt\">\n                    <rect key=\"frame\" x=\"404\" y=\"6\" width=\"43\" height=\"40\"/>\n                    <buttonCell key=\"cell\" type=\"push\" bezelStyle=\"rounded\" image=\"NSTouchBarDeleteTemplate\" imagePosition=\"only\" alignment=\"center\" controlSize=\"large\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"eGS-No-7T6\">\n                        <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"resetFontClick:\" target=\"T8p-iy-4mZ\" id=\"hsT-fL-Bmp\"/>\n                    </connections>\n                </button>\n                <textField toolTip=\"This is the font that will be used to display this overlay.\" focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"A3J-oM-iPq\">\n                    <rect key=\"frame\" x=\"150\" y=\"11\" width=\"200\" height=\"30\"/>\n                    <constraints>\n                        <constraint firstAttribute=\"width\" constant=\"200\" id=\"Ou0-GE-uCU\"/>\n                    </constraints>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" borderStyle=\"bezel\" title=\"Label\" bezelStyle=\"round\" id=\"DeA-4e-fB4\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"cw9-dZ-q2W\">\n                    <rect key=\"frame\" x=\"107\" y=\"18\" width=\"37\" height=\"17\"/>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" alignment=\"right\" title=\"Font:\" id=\"qsb-PQ-5OH\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <button toolTip=\"Change font\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"PoK-PJ-h6f\">\n                    <rect key=\"frame\" x=\"352\" y=\"6\" width=\"52\" height=\"40\"/>\n                    <buttonCell key=\"cell\" type=\"push\" bezelStyle=\"rounded\" image=\"NSFontPanel\" imagePosition=\"only\" alignment=\"center\" controlSize=\"large\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"PlT-pz-6ef\">\n                        <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"changeFontClick:\" target=\"T8p-iy-4mZ\" id=\"hxY-mF-meb\"/>\n                    </connections>\n                </button>\n            </subviews>\n            <constraints>\n                <constraint firstItem=\"A3J-oM-iPq\" firstAttribute=\"top\" secondItem=\"5jY-MV-o3B\" secondAttribute=\"bottom\" constant=\"22\" id=\"17k-Po-hbs\"/>\n                <constraint firstItem=\"7Wo-dF-cCr\" firstAttribute=\"top\" secondItem=\"fYk-Ks-9Iw\" secondAttribute=\"bottom\" constant=\"22\" id=\"Doe-R5-ZGE\"/>\n                <constraint firstItem=\"5jY-MV-o3B\" firstAttribute=\"top\" secondItem=\"7Wo-dF-cCr\" secondAttribute=\"bottom\" constant=\"22\" id=\"DzD-du-Htp\"/>\n                <constraint firstItem=\"hFM-UZ-T70\" firstAttribute=\"top\" secondItem=\"fYk-Ks-9Iw\" secondAttribute=\"bottom\" constant=\"28\" id=\"EAx-W8-Omf\"/>\n                <constraint firstItem=\"fYk-Ks-9Iw\" firstAttribute=\"top\" secondItem=\"T8p-iy-4mZ\" secondAttribute=\"top\" constant=\"22\" id=\"H0Z-yS-xwt\"/>\n                <constraint firstItem=\"A3J-oM-iPq\" firstAttribute=\"leading\" secondItem=\"cw9-dZ-q2W\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"HkK-9B-qQ4\"/>\n                <constraint firstItem=\"42k-s1-y00\" firstAttribute=\"centerX\" secondItem=\"VAs-nn-glQ\" secondAttribute=\"centerX\" id=\"IWE-HR-272\"/>\n                <constraint firstItem=\"HXi-fo-A8E\" firstAttribute=\"leading\" secondItem=\"VAs-nn-glQ\" secondAttribute=\"trailing\" constant=\"55\" id=\"KrK-wG-spa\"/>\n                <constraint firstItem=\"5jY-MV-o3B\" firstAttribute=\"firstBaseline\" secondItem=\"jbv-Al-Uls\" secondAttribute=\"firstBaseline\" id=\"NRF-cP-Wwe\"/>\n                <constraint firstItem=\"A3J-oM-iPq\" firstAttribute=\"firstBaseline\" secondItem=\"cw9-dZ-q2W\" secondAttribute=\"firstBaseline\" id=\"Nah-sH-heS\"/>\n                <constraint firstItem=\"lBk-NQ-Rjz\" firstAttribute=\"leading\" secondItem=\"42k-s1-y00\" secondAttribute=\"trailing\" constant=\"55\" id=\"RuQ-pm-YHg\"/>\n                <constraint firstItem=\"7Wo-dF-cCr\" firstAttribute=\"leading\" secondItem=\"uHM-CZ-kI1\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"US5-06-jWs\"/>\n                <constraint firstItem=\"CgG-gW-q2H\" firstAttribute=\"centerX\" secondItem=\"VAs-nn-glQ\" secondAttribute=\"centerX\" id=\"UyW-CC-W26\"/>\n                <constraint firstItem=\"5jY-MV-o3B\" firstAttribute=\"leading\" secondItem=\"jbv-Al-Uls\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"Wd0-07-Pd2\"/>\n                <constraint firstItem=\"5jY-MV-o3B\" firstAttribute=\"leading\" secondItem=\"T8p-iy-4mZ\" secondAttribute=\"leading\" constant=\"150\" id=\"ZXt-by-RT8\"/>\n                <constraint firstItem=\"HXi-fo-A8E\" firstAttribute=\"firstBaseline\" secondItem=\"hFM-UZ-T70\" secondAttribute=\"firstBaseline\" id=\"ae1-av-CqK\"/>\n                <constraint firstItem=\"fYk-Ks-9Iw\" firstAttribute=\"leading\" secondItem=\"T8p-iy-4mZ\" secondAttribute=\"leading\" constant=\"150\" id=\"cQP-nf-lyc\"/>\n                <constraint firstItem=\"42k-s1-y00\" firstAttribute=\"centerY\" secondItem=\"1l4-Hf-IvH\" secondAttribute=\"centerY\" id=\"hTx-1t-NWQ\"/>\n                <constraint firstItem=\"VAs-nn-glQ\" firstAttribute=\"leading\" secondItem=\"hFM-UZ-T70\" secondAttribute=\"trailing\" constant=\"55\" id=\"hpx-1C-C7F\"/>\n                <constraint firstItem=\"Egt-BD-zPe\" firstAttribute=\"firstBaseline\" secondItem=\"hFM-UZ-T70\" secondAttribute=\"firstBaseline\" id=\"jto-h4-cuJ\"/>\n                <constraint firstItem=\"CgG-gW-q2H\" firstAttribute=\"top\" secondItem=\"VAs-nn-glQ\" secondAttribute=\"bottom\" constant=\"19\" id=\"l7s-uQ-uY5\"/>\n                <constraint firstItem=\"hFM-UZ-T70\" firstAttribute=\"leading\" secondItem=\"uHM-CZ-kI1\" secondAttribute=\"trailing\" constant=\"16\" id=\"lgD-qE-hoY\"/>\n                <constraint firstItem=\"VAs-nn-glQ\" firstAttribute=\"firstBaseline\" secondItem=\"hFM-UZ-T70\" secondAttribute=\"firstBaseline\" id=\"llf-7c-zFd\"/>\n                <constraint firstItem=\"Egt-BD-zPe\" firstAttribute=\"leading\" secondItem=\"7Wo-dF-cCr\" secondAttribute=\"trailing\" constant=\"22\" id=\"mK6-hf-ycH\"/>\n                <constraint firstItem=\"lBk-NQ-Rjz\" firstAttribute=\"centerY\" secondItem=\"1l4-Hf-IvH\" secondAttribute=\"centerY\" id=\"mno-as-55c\"/>\n                <constraint firstItem=\"PoK-PJ-h6f\" firstAttribute=\"leading\" secondItem=\"A3J-oM-iPq\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"moS-EE-kGg\"/>\n                <constraint firstItem=\"7Wo-dF-cCr\" firstAttribute=\"top\" secondItem=\"uHM-CZ-kI1\" secondAttribute=\"top\" id=\"oUG-nS-FjG\"/>\n                <constraint firstItem=\"JnO-I8-Uqt\" firstAttribute=\"leading\" secondItem=\"PoK-PJ-h6f\" secondAttribute=\"trailing\" constant=\"12\" symbolic=\"YES\" id=\"pQK-pE-6oO\"/>\n                <constraint firstItem=\"JnO-I8-Uqt\" firstAttribute=\"centerY\" secondItem=\"A3J-oM-iPq\" secondAttribute=\"centerY\" id=\"qHW-h1-Rn9\"/>\n                <constraint firstItem=\"42k-s1-y00\" firstAttribute=\"leading\" secondItem=\"1l4-Hf-IvH\" secondAttribute=\"trailing\" constant=\"55\" id=\"t7Y-IY-O9Q\"/>\n                <constraint firstItem=\"PoK-PJ-h6f\" firstAttribute=\"centerY\" secondItem=\"A3J-oM-iPq\" secondAttribute=\"centerY\" id=\"tHp-OK-DuU\"/>\n                <constraint firstAttribute=\"bottom\" secondItem=\"A3J-oM-iPq\" secondAttribute=\"bottom\" constant=\"11\" id=\"tzR-ah-R78\"/>\n                <constraint firstItem=\"7Wo-dF-cCr\" firstAttribute=\"leading\" secondItem=\"T8p-iy-4mZ\" secondAttribute=\"leading\" constant=\"150\" id=\"w74-kI-TBv\"/>\n                <constraint firstItem=\"42k-s1-y00\" firstAttribute=\"top\" secondItem=\"CgG-gW-q2H\" secondAttribute=\"bottom\" constant=\"19\" id=\"xVX-r6-jfP\"/>\n                <constraint firstItem=\"A3J-oM-iPq\" firstAttribute=\"leading\" secondItem=\"T8p-iy-4mZ\" secondAttribute=\"leading\" constant=\"150\" id=\"xsc-dH-PF9\"/>\n            </constraints>\n            <connections>\n                <outlet property=\"displaysPopup\" destination=\"5jY-MV-o3B\" id=\"TR2-V4-88z\"/>\n                <outlet property=\"enabledButton\" destination=\"fYk-Ks-9Iw\" id=\"dEx-E3-qHa\"/>\n                <outlet property=\"fontLabel\" destination=\"A3J-oM-iPq\" id=\"PhE-zS-svu\"/>\n                <outlet property=\"posBottomCenter\" destination=\"42k-s1-y00\" id=\"xXy-Jd-AvX\"/>\n                <outlet property=\"posBottomLeft\" destination=\"1l4-Hf-IvH\" id=\"ZyR-b3-eaZ\"/>\n                <outlet property=\"posBottomRight\" destination=\"lBk-NQ-Rjz\" id=\"oDv-8Q-RJE\"/>\n                <outlet property=\"posRandom\" destination=\"Egt-BD-zPe\" id=\"gef-DE-8cv\"/>\n                <outlet property=\"posScreenCenter\" destination=\"CgG-gW-q2H\" id=\"jsJ-NY-7Uz\"/>\n                <outlet property=\"posTopCenter\" destination=\"VAs-nn-glQ\" id=\"kpn-1a-HFx\"/>\n                <outlet property=\"posTopLeft\" destination=\"hFM-UZ-T70\" id=\"KiQ-He-IT7\"/>\n                <outlet property=\"posTopRight\" destination=\"HXi-fo-A8E\" id=\"sFT-Cm-7Pi\"/>\n            </connections>\n            <point key=\"canvasLocation\" x=\"717\" y=\"638\"/>\n        </customView>\n        <customView id=\"dIH-yk-sga\" userLabel=\"Message Text File View\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"580\" height=\"96\"/>\n            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n            <subviews>\n                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"kiT-4Q-OO1\">\n                    <rect key=\"frame\" x=\"82\" y=\"65\" width=\"62\" height=\"17\"/>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" alignment=\"right\" title=\"Text File:\" id=\"Lnb-wW-Bds\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <textField focusRingType=\"none\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Urv-xq-s3M\">\n                    <rect key=\"frame\" x=\"150\" y=\"63\" width=\"330\" height=\"22\"/>\n                    <constraints>\n                        <constraint firstAttribute=\"width\" constant=\"330\" id=\"M0Y-p7-XVc\"/>\n                    </constraints>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" scrollable=\"YES\" lineBreakMode=\"clipping\" selectable=\"YES\" editable=\"YES\" sendsActionOnEndEditing=\"YES\" borderStyle=\"bezel\" placeholderString=\"Type your script location (eg : /Users/Shared/test.sh)\" drawsBackground=\"YES\" id=\"qaC-Iq-3R6\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n            </subviews>\n            <constraints>\n                <constraint firstItem=\"Urv-xq-s3M\" firstAttribute=\"leading\" secondItem=\"kiT-4Q-OO1\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"Q6t-6a-gPf\"/>\n                <constraint firstItem=\"Urv-xq-s3M\" firstAttribute=\"top\" secondItem=\"dIH-yk-sga\" secondAttribute=\"top\" constant=\"11\" id=\"UrG-ce-awO\"/>\n                <constraint firstItem=\"Urv-xq-s3M\" firstAttribute=\"firstBaseline\" secondItem=\"kiT-4Q-OO1\" secondAttribute=\"firstBaseline\" id=\"lVg-vv-CdV\"/>\n                <constraint firstItem=\"Urv-xq-s3M\" firstAttribute=\"leading\" secondItem=\"dIH-yk-sga\" secondAttribute=\"leading\" constant=\"150\" id=\"zqM-tm-vHL\"/>\n            </constraints>\n            <point key=\"canvasLocation\" x=\"-161\" y=\"124\"/>\n        </customView>\n        <viewController id=\"Gwi-Sj-fW9\" userLabel=\"Popover View Controller\">\n            <connections>\n                <outlet property=\"view\" destination=\"go3-Lb-KNk\" id=\"U68-sO-Btm\"/>\n            </connections>\n        </viewController>\n        <popover behavior=\"t\" id=\"mNc-DU-HEx\">\n            <connections>\n                <outlet property=\"contentViewController\" destination=\"Gwi-Sj-fW9\" id=\"9Oa-ay-Gx3\"/>\n            </connections>\n        </popover>\n        <customView id=\"ixa-6o-Glt\" customClass=\"InfoMusicView\" customModule=\"Aerial\" customModuleProvider=\"target\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"580\" height=\"175\"/>\n            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n            <subviews>\n                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"vBx-XF-f0p\">\n                    <rect key=\"frame\" x=\"148\" y=\"123\" width=\"383\" height=\"32\"/>\n                    <constraints>\n                        <constraint firstAttribute=\"width\" constant=\"379\" id=\"fIG-ab-88q\"/>\n                    </constraints>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" title=\"Applications that show up in your menubar media remote will show up in Aerial\" id=\"f2R-nZ-9Ap\">\n                        <font key=\"font\" metaFont=\"system\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n            </subviews>\n            <constraints>\n                <constraint firstItem=\"vBx-XF-f0p\" firstAttribute=\"leading\" secondItem=\"ixa-6o-Glt\" secondAttribute=\"leading\" constant=\"150\" id=\"6Rc-hP-U8f\"/>\n                <constraint firstItem=\"vBx-XF-f0p\" firstAttribute=\"top\" secondItem=\"ixa-6o-Glt\" secondAttribute=\"top\" constant=\"20\" symbolic=\"YES\" id=\"z6Y-r5-1if\"/>\n            </constraints>\n            <point key=\"canvasLocation\" x=\"-840\" y=\"753.5\"/>\n        </customView>\n        <customView id=\"UAz-72-SHK\" userLabel=\"Location Extra View\" customClass=\"InfoLocationView\" customModule=\"Aerial\" customModuleProvider=\"target\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"595\" height=\"50\"/>\n            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n            <subviews>\n                <popUpButton toolTip=\"How long should each text appear\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"oQi-Jg-Zmj\">\n                    <rect key=\"frame\" x=\"145\" y=\"5\" width=\"150\" height=\"40\"/>\n                    <popUpButtonCell key=\"cell\" type=\"push\" title=\"Always\" bezelStyle=\"rounded\" alignment=\"left\" controlSize=\"large\" lineBreakMode=\"truncatingTail\" state=\"on\" borderStyle=\"borderAndBezel\" imageScaling=\"proportionallyDown\" inset=\"2\" selectedItem=\"00L-iz-YPw\" id=\"o4O-qy-FA4\">\n                        <behavior key=\"behavior\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" size=\"14\" name=\"HelveticaNeue\"/>\n                        <menu key=\"menu\" id=\"tg0-mv-rLW\">\n                            <items>\n                                <menuItem title=\"Always\" state=\"on\" id=\"00L-iz-YPw\"/>\n                                <menuItem title=\"For 10 Seconds\" id=\"c5r-2s-uOW\"/>\n                            </items>\n                        </menu>\n                    </popUpButtonCell>\n                    <connections>\n                        <action selector=\"showTimeChange:\" target=\"UAz-72-SHK\" id=\"dww-7i-af6\"/>\n                    </connections>\n                </popUpButton>\n                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"0le-4N-WhS\">\n                    <rect key=\"frame\" x=\"100\" y=\"18\" width=\"44\" height=\"17\"/>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" alignment=\"right\" title=\"Show:\" id=\"w4U-mQ-Zz2\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n            </subviews>\n            <constraints>\n                <constraint firstAttribute=\"bottom\" secondItem=\"oQi-Jg-Zmj\" secondAttribute=\"bottom\" constant=\"11\" id=\"05b-fA-7WZ\"/>\n                <constraint firstItem=\"oQi-Jg-Zmj\" firstAttribute=\"firstBaseline\" secondItem=\"0le-4N-WhS\" secondAttribute=\"firstBaseline\" id=\"C8h-aX-cAO\"/>\n                <constraint firstItem=\"oQi-Jg-Zmj\" firstAttribute=\"top\" secondItem=\"UAz-72-SHK\" secondAttribute=\"top\" constant=\"11\" id=\"SSR-Na-Lsj\"/>\n                <constraint firstItem=\"oQi-Jg-Zmj\" firstAttribute=\"leading\" secondItem=\"UAz-72-SHK\" secondAttribute=\"leading\" constant=\"150\" id=\"aI4-Gd-DFw\"/>\n                <constraint firstItem=\"oQi-Jg-Zmj\" firstAttribute=\"leading\" secondItem=\"0le-4N-WhS\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"oO8-AI-8AO\"/>\n            </constraints>\n            <connections>\n                <outlet property=\"showTimePopup\" destination=\"oQi-Jg-Zmj\" id=\"4I3-hq-jTA\"/>\n            </connections>\n            <point key=\"canvasLocation\" x=\"-112\" y=\"1180\"/>\n        </customView>\n        <customView id=\"wFi-1P-F0m\" userLabel=\"Message Extra View\" customClass=\"InfoMessageView\" customModule=\"Aerial\" customModuleProvider=\"target\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"595\" height=\"52\"/>\n            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n            <subviews>\n                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"HZB-E1-LF5\">\n                    <rect key=\"frame\" x=\"45\" y=\"20\" width=\"99\" height=\"17\"/>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" alignment=\"right\" title=\"Message type:\" id=\"MnS-Bc-nML\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <popUpButton verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Car-4i-fsE\">\n                    <rect key=\"frame\" x=\"145\" y=\"7\" width=\"133\" height=\"40\"/>\n                    <popUpButtonCell key=\"cell\" type=\"push\" title=\"Text\" bezelStyle=\"rounded\" alignment=\"left\" controlSize=\"large\" lineBreakMode=\"truncatingTail\" state=\"on\" borderStyle=\"borderAndBezel\" imageScaling=\"proportionallyDown\" inset=\"2\" selectedItem=\"rgn-Kj-il5\" id=\"g8I-Jt-FCO\">\n                        <behavior key=\"behavior\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" size=\"14\" name=\"HelveticaNeue\"/>\n                        <menu key=\"menu\" id=\"3lb-e0-QOO\">\n                            <items>\n                                <menuItem title=\"Text\" state=\"on\" id=\"rgn-Kj-il5\"/>\n                                <menuItem title=\"Shell script\" id=\"dl3-Ki-cEH\"/>\n                                <menuItem title=\"Text File\" hidden=\"YES\" id=\"kQs-A5-Ody\"/>\n                            </items>\n                        </menu>\n                    </popUpButtonCell>\n                    <connections>\n                        <action selector=\"messageTypeChange:\" target=\"wFi-1P-F0m\" id=\"1Tf-Kr-Qrc\"/>\n                    </connections>\n                </popUpButton>\n            </subviews>\n            <constraints>\n                <constraint firstAttribute=\"trailing\" secondItem=\"Car-4i-fsE\" secondAttribute=\"trailing\" constant=\"322\" id=\"9cp-AW-iTX\"/>\n                <constraint firstItem=\"Car-4i-fsE\" firstAttribute=\"leading\" secondItem=\"HZB-E1-LF5\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"BI1-6j-OwM\"/>\n                <constraint firstItem=\"Car-4i-fsE\" firstAttribute=\"top\" secondItem=\"wFi-1P-F0m\" secondAttribute=\"top\" constant=\"11\" id=\"QS1-Ts-t2P\"/>\n                <constraint firstItem=\"Car-4i-fsE\" firstAttribute=\"firstBaseline\" secondItem=\"HZB-E1-LF5\" secondAttribute=\"firstBaseline\" id=\"jyO-RY-EAV\"/>\n                <constraint firstItem=\"Car-4i-fsE\" firstAttribute=\"leading\" secondItem=\"wFi-1P-F0m\" secondAttribute=\"leading\" constant=\"150\" id=\"o28-vU-ZhI\"/>\n            </constraints>\n            <connections>\n                <outlet property=\"messageTextChange\" destination=\"ehG-nq-Wse\" id=\"cSX-Ia-QDw\"/>\n                <outlet property=\"messageTextView\" destination=\"ehG-nq-Wse\" id=\"Zb3-Ju-MnL\"/>\n                <outlet property=\"messageType\" destination=\"Car-4i-fsE\" id=\"C9C-yE-nhj\"/>\n                <outlet property=\"shellRefreshPeriodicity\" destination=\"Ev7-MY-EGf\" id=\"SFf-87-hkP\"/>\n                <outlet property=\"shellScript\" destination=\"mQk-nn-Wxa\" id=\"Wqk-HN-UaD\"/>\n                <outlet property=\"shellScriptLabel\" destination=\"ZIt-5C-mn7\" id=\"lOG-sF-6wt\"/>\n                <outlet property=\"shellScriptTest\" destination=\"7LK-MG-r8x\" id=\"STF-OZ-nyD\"/>\n            </connections>\n            <point key=\"canvasLocation\" x=\"549.5\" y=\"1181\"/>\n        </customView>\n        <customView id=\"d6p-Wj-XTq\" userLabel=\"Battery Extra View\" customClass=\"InfoBatteryView\" customModule=\"Aerial\" customModuleProvider=\"target\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"595\" height=\"39\"/>\n            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n            <subviews>\n                <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"WYI-OI-dE9\">\n                    <rect key=\"frame\" x=\"147\" y=\"8.5\" width=\"186\" height=\"22\"/>\n                    <buttonCell key=\"cell\" type=\"check\" title=\"Hide when battery is full\" bezelStyle=\"regularSquare\" imagePosition=\"left\" controlSize=\"large\" state=\"on\" inset=\"2\" id=\"Hq7-7H-DW7\">\n                        <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"hideWhenFullCheck:\" target=\"d6p-Wj-XTq\" id=\"NyZ-QA-Ib1\"/>\n                    </connections>\n                </button>\n            </subviews>\n            <constraints>\n                <constraint firstItem=\"WYI-OI-dE9\" firstAttribute=\"leading\" secondItem=\"d6p-Wj-XTq\" secondAttribute=\"leading\" constant=\"150\" id=\"Kau-4T-kPK\"/>\n                <constraint firstItem=\"WYI-OI-dE9\" firstAttribute=\"top\" secondItem=\"d6p-Wj-XTq\" secondAttribute=\"top\" constant=\"11\" id=\"N2P-PP-Tsh\"/>\n                <constraint firstAttribute=\"bottom\" secondItem=\"WYI-OI-dE9\" secondAttribute=\"bottom\" constant=\"11\" id=\"pJ8-xf-fyp\"/>\n            </constraints>\n            <connections>\n                <outlet property=\"hideWhenFull\" destination=\"WYI-OI-dE9\" id=\"03H-Mq-T1v\"/>\n            </connections>\n            <point key=\"canvasLocation\" x=\"-816\" y=\"397\"/>\n        </customView>\n    </objects>\n    <resources>\n        <image name=\"NSFontPanel\" width=\"32\" height=\"32\"/>\n        <image name=\"NSListViewTemplate\" width=\"21\" height=\"15\"/>\n        <image name=\"NSStatusAvailable\" width=\"16\" height=\"16\"/>\n        <image name=\"NSTouchBarDeleteTemplate\" width=\"19\" height=\"22\"/>\n        <image name=\"openweather_logo\" width=\"180\" height=\"80\"/>\n        <image name=\"screen0\" width=\"720\" height=\"400\"/>\n        <image name=\"text.bubble\" catalog=\"system\" width=\"22\" height=\"20\"/>\n    </resources>\n</document>\n"
  },
  {
    "path": "Resources/MainUI/Settings panels/SourcesViewController.swift",
    "content": "//\n//  SourcesViewController.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 18/07/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Cocoa\n\nclass SourcesViewController: NSViewController {\n    var customVideoController: CustomVideoController?\n\n    @IBOutlet var sourceOutlineView: SourceOutlineView!\n\n    @IBOutlet var addOnlineWindow: NSWindow!\n    @IBOutlet var addOnlineTextField: NSTextField!\n\n    @IBOutlet var addLocalWindow: NSWindow!\n    @IBOutlet var addLocalTextfield: NSTextField!\n\n    @IBOutlet var addLocalButton: NSButton!\n    @IBOutlet var addOnlineButton: NSButton!\n    @IBOutlet var getMoreVideosButton: NSButton!\n    @IBOutlet var downloadAllVideosButton: NSButton!\n\n    @IBOutlet var refreshPeriodicity: NSPopUpButton!\n\n    @IBOutlet var allSpinner: NSProgressIndicator!\n    var selectedSource: Source?\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n        allSpinner.isHidden = true\n        sourceOutlineView.dataSource = self\n        sourceOutlineView.delegate = self\n\n        addLocalButton.setIcons(\"folder\")\n        addOnlineButton.setIcons(\"antenna.radiowaves.left.and.right\")\n        getMoreVideosButton.setIcons(\"cloud\")\n        downloadAllVideosButton.setIcons(\"arrow.down.circle\")\n        refreshPeriodicity.selectItem(at: PrefsVideos.intRefreshPeriodicity)\n\n        VideoManager.sharedInstance.addCallback { done, total in\n            debugLog(\"vmsourcecallback \\(done) \\(total) \")\n            if total == 0 {\n                self.sourceOutlineView.reloadData()\n                self.allSpinner.stopAnimation(self)\n                self.allSpinner.isHidden = true\n                self.downloadAllVideosButton.isEnabled = true\n                self.sourceOutlineView.expandItem(nil, expandChildren: true)\n            }\n        }\n\n        VideoList.instance.addCallback {\n            debugLog(\"sourcecallback\")\n            self.sourceOutlineView.reloadData()\n            self.sourceOutlineView.expandItem(nil, expandChildren: true)\n        }\n    }\n\n    @IBAction func refreshPeriodicityChange(_ sender: NSPopUpButton) {\n        PrefsVideos.refreshPeriodicity = RefreshPeriodicity(rawValue: sender.indexOfSelectedItem)!\n    }\n\n    @IBAction func getMoreVideosClick(_ sender: NSButton) {\n        let workspace = NSWorkspace.shared\n        let url = URL(string: \"https://aerialscreensaver.github.io/morevideos.html\")!\n        workspace.open(url)\n        //\n    }\n\n    @IBAction func downloadAllClick(_ sender: NSButton) {\n        Cache.ensureDownload {\n            self.allSpinner.startAnimation(self)\n            self.allSpinner.isHidden = false\n            self.downloadAllVideosButton.isEnabled = false\n\n            for video in VideoList.instance.videos.filter({ !$0.isAvailableOffline && !PrefsVideos.hidden.contains($0.id) }) {\n                VideoManager.sharedInstance.queueDownload(video)\n            }\n        }\n    }\n\n    @IBAction func addLocalClick(_ sender: NSButton) {\n        addLocalWindow.makeKeyAndOrderFront(self)\n        /*\n        // We also load our CustomVideos nib here\n        let bundle = Bundle(for: CustomVideoController.self)\n\n        customVideoController = CustomVideoController()\n        var topLevelObjects: NSArray? = NSArray()\n        if !bundle.loadNibNamed(NSNib.Name(\"CustomVideos\"),\n                            owner: customVideoController,\n                            topLevelObjects: &topLevelObjects) {\n            errorLog(\"Could not load nib for CustomVideos, please report\")\n        }\n        DispatchQueue.main.async {\n            self.customVideoController!.windowDidLoad()\n            self.customVideoController!.show(sender: sender, controller: self)\n            //self.customVideoController!.window!.makeKeyAndOrderFront(self)\n        }*/\n    }\n\n    @IBAction func addLocalValidate(_ sender: Any) {\n        let url = URL(fileURLWithPath: addLocalTextfield.stringValue)\n\n        SourceList.processPathForVideos(url: url)\n        addLocalWindow.close()\n        addLocalTextfield.stringValue = \"\"\n        sourceOutlineView.reloadData()\n        sourceOutlineView.expandItem(nil, expandChildren: true)\n\n    }\n\n    @IBAction func findMoreVideos(_ sender: Any) {\n        let workspace = NSWorkspace.shared\n        let url = URL(string: \"https://aerialscreensaver.github.io/morevideos.html\")!\n        workspace.open(url)\n    }\n\n    @IBAction func addLocalCancel(_ sender: Any) {\n        addLocalWindow.close()\n        addLocalTextfield.stringValue = \"\"\n    }\n\n    @IBAction func addOnlineClick(_ sender: Any) {\n        debugLog(\"Add online clicked\")\n        addOnlineWindow.makeKeyAndOrderFront(self)\n    }\n\n    @IBAction func addOnlineDownload(_ sender: Any) {\n        debugLog(\"Add online validated\")\n        let trimmedString = addOnlineTextField.stringValue.trimmingCharacters(in: .whitespacesAndNewlines)\n\n        if let url = URL(string: trimmedString) {\n            debugLog(\"URL was parsed, fetching\")\n            SourceList.fetchOnlineManifest(url: url)\n            addOnlineWindow.close()\n            addOnlineTextField.stringValue = \"\"\n            sourceOutlineView.reloadData()\n            sourceOutlineView.expandItem(nil, expandChildren: true)\n        } else {\n            debugLog(\"URL was NOT parsed\")\n            Aerial.helper.showErrorAlert(question: \"Non valid URL\",\n                                  text: \"Please type a valid URL to an Aerial source (see the more videos button), and make sure there are no trailing characters.\")\n        }\n    }\n\n    @IBAction func addOnlineCancel(_ sender: Any) {\n        addOnlineWindow.close()\n        addOnlineTextField.stringValue = \"\"\n    }\n\n}\n\nextension SourcesViewController: SourceOutlineViewDelegate {\n\n    func outlineView(outlineView: NSOutlineView, menuForItem item: Any) -> NSMenu? {\n        if let source = item as? Source {\n            let menu = NSMenu()\n\n            selectedSource = source\n            let mitem = NSMenuItem(title: \"Remove source\", action: #selector(removeSource(_:)), keyEquivalent: \"\")\n            mitem.setIcons(\"eye.slash\")\n            menu.addItem(mitem)\n\n            return menu\n        }\n\n        return nil\n    }\n\n    @objc func removeSource(_ sender: Any) {\n        if let source = selectedSource {\n            // swiftlint:disable:next line_length\n            if Aerial.helper.showAlert(question: \"Remove a source\", text: \"This will remove all files and videos relating to this source. Are you sure you want to proceed? \\n\\nYou will need to restart System Preferences to complete the operation.\", button1: \"Remove Source\", button2: \"Cancel\") {\n                source.wipeFromDisk()\n                sourceOutlineView.reloadData()\n                sourceOutlineView.expandItem(nil, expandChildren: true)\n\n            }\n        }\n    }\n}\n\nextension SourcesViewController: NSOutlineViewDataSource, NSOutlineViewDelegate {\n\n    // item == nil means it's the \"root\" row of the outline view, which is not visible\n    func outlineView(_ outlineView: NSOutlineView, child index: Int, ofItem item: Any?) -> Any {\n        if item == nil {\n            return SourceList.categorizedSourceList()[index]\n        } else {\n            if let item = item as? SourceHeader {\n                return item.sources[index]\n            } else {\n                return 0\n            }\n        }\n    }\n\n    // Tell how many children each row has:\n    func outlineView(_ outlineView: NSOutlineView, numberOfChildrenOfItem item: Any?) -> Int {\n        if item == nil {\n            return SourceList.categorizedSourceList().count\n        } else {\n            if let item = item as? SourceHeader {\n                return item.sources.count\n            } else {\n                return 1\n            }\n        }\n    }\n\n    // Tell whether the row is expandable.\n    func outlineView(_ outlineView: NSOutlineView, isItemExpandable item: Any) -> Bool {\n        guard let _ = item as? SourceHeader else { return false }\n        return true\n    }\n\n    // Set the content for each row/column element\n    // swiftlint:disable cyclomatic_complexity\n    func outlineView(_ outlineView: NSOutlineView, viewFor tableColumn: NSTableColumn?, item: Any) -> NSView? {\n\n        guard let columnIdentifier = tableColumn?.identifier.rawValue else {\n            return nil\n        }\n\n        if let sourceHeader = item as? SourceHeader {\n            if columnIdentifier == \"valueColumn\" {\n                let cell = outlineView.makeView(withIdentifier:\n                                                    NSUserInterfaceItemIdentifier(rawValue: \"valueColumnCell\"), owner: self) as! DescriptionCellView\n                cell.titleLabel.stringValue = sourceHeader.name\n                cell.descriptionLabel.stringValue = \"\"\n                cell.lastUpdatedLabel.stringValue = \"\"\n                cell.imageScene1.isHidden = true\n                cell.imageScene2.isHidden = true\n                cell.imageScene3.isHidden = true\n                cell.imageScene4.isHidden = true\n                cell.imageScene5.isHidden = true\n                cell.imageScene6.isHidden = true\n                cell.videoCount.stringValue = \"\"\n                cell.licenseButton.isHidden = true\n                cell.moreButton.isHidden = true\n                cell.imageFilm.isHidden = true\n                cell.refreshNowButton.isHidden = true\n                return cell\n            } else {\n                return nil\n            }\n        }\n\n        let source = item as! Source\n\n        switch columnIdentifier {\n        case \"isSelected\":\n            let cell = outlineView.makeView(withIdentifier:\n                                                NSUserInterfaceItemIdentifier(rawValue: \"isSelectedCell\"), owner: self) as! CheckboxCellView\n            cell.checkboxButton.state = source.isEnabled() ? .on : .off\n            cell.delegate = self\n            cell.item = item\n            return cell\n\n        case \"valueColumn\":\n            let cell = outlineView.makeView(withIdentifier:\n                                                NSUserInterfaceItemIdentifier(rawValue: \"valueColumnCell\"), owner: self) as! DescriptionCellView\n            cell.item = source\n            cell.titleLabel.stringValue = source.name\n            cell.descriptionLabel.stringValue = source.description\n            cell.lastUpdatedLabel.stringValue = \"Last updated: \" + source.lastUpdated()\n            cell.imageScene1.isHidden = !source.scenes.contains(.nature)\n            cell.imageScene2.isHidden = !source.scenes.contains(.city)\n            cell.imageScene3.isHidden = !source.scenes.contains(.space)\n            cell.imageScene4.isHidden = !source.scenes.contains(.sea)\n            cell.imageScene5.isHidden = !source.scenes.contains(.beach)\n            cell.imageScene6.isHidden = !source.scenes.contains(.countryside)\n\n            if source.isEnabled() {\n                cell.imageFilm.isHidden = false\n\n                let totalCount = VideoList.instance.videos.filter({ $0.source.name == source.name }).count\n                let downloadedCount = VideoList.instance.videos.filter({ $0.source.name == source.name && $0.isAvailableOffline }).count\n                let size = source.diskUsage().rounded(toPlaces: 1)\n\n                if totalCount == downloadedCount {\n                    cell.videoCount.stringValue = \"\\(totalCount) videos\"\n                } else {\n                    cell.videoCount.stringValue = \"\\(downloadedCount) of \\(totalCount) videos downloaded\"\n                }\n\n                if !source.isCachable && source.type != .local {\n                    cell.videoCount.stringValue.append(\", \\(size) GB on disk\")\n                }\n            } else {\n                cell.imageFilm.isHidden = true\n\n                cell.videoCount.stringValue = \"\"\n            }\n\n            cell.licenseButton.isHidden = (source.license == \"\")\n            cell.moreButton.isHidden = (source.more == \"\")\n            cell.refreshNowButton.isHidden = false\n\n            return cell\n        case \"actionColumn\":\n            let cell = outlineView.makeView(withIdentifier:\n                        NSUserInterfaceItemIdentifier(rawValue: columnIdentifier), owner: self) as! ActionCellView\n            cell.source = source\n            cell.spinner.stopAnimation(self)\n            cell.spinner.isHidden = true\n\n            if source.type == .local {\n                cell.actionButton.setLargeIcon(\"folder\")\n                cell.actionButton.isEnabled = true\n            } else {\n                if VideoList.instance.videos.filter({ $0.source.name == source.name && !$0.isAvailableOffline }).isEmpty {\n                    cell.actionButton.image = Aerial.helper.getMiniSymbol(\"checkmark.circle.fill\", tint: .systemGreen)\n                    cell.actionButton.isEnabled = false\n                } else {\n                    cell.actionButton.setLargeIcon(\"arrow.down.circle\")\n                    cell.actionButton.isEnabled = true\n                }\n            }\n            return cell\n\n        default:\n            let cell = outlineView.makeView(withIdentifier:\n                        NSUserInterfaceItemIdentifier(rawValue: columnIdentifier), owner: self) as! NSTableCellView\n            cell.textField?.stringValue = \"\"\n            return cell\n        }\n    }\n\n    func outlineView(_ outlineView: NSOutlineView, heightOfRowByItem item: Any) -> CGFloat {\n        if item is SourceHeader {\n            return 24\n        } else {\n            return 70\n        }\n    }\n\n/*\n    func outlineView(_ outlineView: NSOutlineView, dataCellFor tableColumn: NSTableColumn?, item: Any) -> NSCell? {\n        print(\"dcf\")\n        if let item = item as? SourceHeader {\n            return NSTextFieldCell(textCell: item.name)\n        }\n\n        return nil\n    }*/\n}\n\nextension SourcesViewController: CheckboxCellViewDelegate {\n    /// A delegate function where we can act on update from the checkbox in the \"Is Selected\" column\n    func checkboxCellView(_ cell: CheckboxCellView, didChangeState state: NSControl.StateValue) {\n        guard let item = cell.item as? Source else { return }\n\n        // The row and its children are selected if state == .on\n        item.setEnabled(state == .on)\n\n        // This is more efficient than calling reload on every child since collapsed children are\n        // not reloaded. They will be reloaded when they become visible\n        DispatchQueue.main.async {\n            self.sourceOutlineView.reloadItem(item, reloadChildren: true)\n        }\n    }\n}\n"
  },
  {
    "path": "Resources/MainUI/Settings panels/SourcesViewController.xib",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.Cocoa.XIB\" version=\"3.0\" toolsVersion=\"23504\" targetRuntime=\"MacOSX.Cocoa\" propertyAccessControl=\"none\" useAutolayout=\"YES\" customObjectInstantitationMethod=\"direct\">\n    <dependencies>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.CocoaPlugin\" version=\"23504\"/>\n        <capability name=\"Image references\" minToolsVersion=\"12.0\"/>\n        <capability name=\"System colors introduced in macOS 10.14\" minToolsVersion=\"10.0\"/>\n        <capability name=\"documents saved in the Xcode 8 format\" minToolsVersion=\"8.0\"/>\n    </dependencies>\n    <objects>\n        <customObject id=\"-2\" userLabel=\"File's Owner\" customClass=\"SourcesViewController\" customModule=\"Aerial\" customModuleProvider=\"target\">\n            <connections>\n                <outlet property=\"addLocalButton\" destination=\"YCA-Kf-OqL\" id=\"E9C-sU-zkW\"/>\n                <outlet property=\"addLocalTextfield\" destination=\"oZ9-Ey-gbW\" id=\"mcS-es-F6H\"/>\n                <outlet property=\"addLocalWindow\" destination=\"Pmx-QU-MSf\" id=\"eYa-DN-kdF\"/>\n                <outlet property=\"addOnlineButton\" destination=\"H7z-UB-Yzx\" id=\"WLY-sV-uAH\"/>\n                <outlet property=\"addOnlineTextField\" destination=\"gxJ-4P-fMD\" id=\"Gmf-Aa-0Bd\"/>\n                <outlet property=\"addOnlineWindow\" destination=\"iB7-4m-6mH\" id=\"v0k-ql-rIf\"/>\n                <outlet property=\"allSpinner\" destination=\"heQ-Ra-4Qf\" id=\"Ni3-FG-fCS\"/>\n                <outlet property=\"downloadAllVideosButton\" destination=\"P2e-fe-Js2\" id=\"E5g-St-pCy\"/>\n                <outlet property=\"getMoreVideosButton\" destination=\"hJ0-L4-qoE\" id=\"GoK-d5-Kxa\"/>\n                <outlet property=\"refreshPeriodicity\" destination=\"FxS-MX-bfw\" id=\"rhZ-kc-M6b\"/>\n                <outlet property=\"sourceOutlineView\" destination=\"vzM-Kh-6SV\" id=\"4vs-WJ-2Ar\"/>\n                <outlet property=\"view\" destination=\"Hz6-mo-xeY\" id=\"0bl-1N-x8E\"/>\n            </connections>\n        </customObject>\n        <customObject id=\"-1\" userLabel=\"First Responder\" customClass=\"FirstResponder\"/>\n        <customObject id=\"-3\" userLabel=\"Application\" customClass=\"NSObject\"/>\n        <customView translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Hz6-mo-xeY\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"813\" height=\"530\"/>\n            <subviews>\n                <scrollView horizontalHuggingPriority=\"500\" verticalHuggingPriority=\"500\" horizontalCompressionResistancePriority=\"75\" verticalCompressionResistancePriority=\"75\" autohidesScrollers=\"YES\" horizontalLineScroll=\"70\" horizontalPageScroll=\"10\" verticalLineScroll=\"70\" verticalPageScroll=\"10\" hasHorizontalScroller=\"NO\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"bBq-pn-VQA\">\n                    <rect key=\"frame\" x=\"16\" y=\"68\" width=\"781\" height=\"408\"/>\n                    <clipView key=\"contentView\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"sZp-jW-Eya\">\n                        <rect key=\"frame\" x=\"1\" y=\"1\" width=\"779\" height=\"406\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <subviews>\n                            <outlineView verticalHuggingPriority=\"750\" allowsExpansionToolTips=\"YES\" columnAutoresizingStyle=\"lastColumnOnly\" alternatingRowBackgroundColors=\"YES\" multipleSelection=\"NO\" autosaveColumns=\"NO\" rowHeight=\"70\" headerView=\"b1V-rc-xZQ\" viewBased=\"YES\" indentationPerLevel=\"13\" outlineTableColumn=\"Ssk-cL-P6o\" id=\"vzM-Kh-6SV\" customClass=\"SourceOutlineView\" customModule=\"Aerial\" customModuleProvider=\"target\">\n                                <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"790\" height=\"381\"/>\n                                <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                                <size key=\"intercellSpacing\" width=\"17\" height=\"0.0\"/>\n                                <color key=\"backgroundColor\" name=\"controlBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                <color key=\"gridColor\" name=\"gridColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                <tableColumns>\n                                    <tableColumn identifier=\"isSelected\" width=\"50\" minWidth=\"50\" maxWidth=\"50\" id=\"Ssk-cL-P6o\">\n                                        <tableHeaderCell key=\"headerCell\" lineBreakMode=\"truncatingTail\" borderStyle=\"border\" title=\"Show\">\n                                            <color key=\"textColor\" name=\"headerTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                            <color key=\"backgroundColor\" name=\"headerColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                        </tableHeaderCell>\n                                        <textFieldCell key=\"dataCell\" lineBreakMode=\"truncatingTail\" selectable=\"YES\" editable=\"YES\" title=\"Text Cell\" id=\"N8Z-lr-o5Q\">\n                                            <font key=\"font\" metaFont=\"system\"/>\n                                            <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                            <color key=\"backgroundColor\" name=\"controlBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                        </textFieldCell>\n                                        <prototypeCellViews>\n                                            <tableCellView identifier=\"isSelectedCell\" id=\"Xuz-Uo-wO2\" customClass=\"CheckboxCellView\" customModule=\"Aerial\" customModuleProvider=\"target\">\n                                                <rect key=\"frame\" x=\"8\" y=\"0.0\" width=\"48\" height=\"68\"/>\n                                                <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                                                <subviews>\n                                                    <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"wGa-S6-kGM\">\n                                                        <rect key=\"frame\" x=\"13\" y=\"23\" width=\"22\" height=\"22\"/>\n                                                        <buttonCell key=\"cell\" type=\"check\" bezelStyle=\"regularSquare\" imagePosition=\"left\" controlSize=\"large\" state=\"on\" inset=\"2\" id=\"Q6G-xu-7Lu\">\n                                                            <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                                                            <font key=\"font\" metaFont=\"system\"/>\n                                                        </buttonCell>\n                                                    </button>\n                                                </subviews>\n                                                <constraints>\n                                                    <constraint firstItem=\"wGa-S6-kGM\" firstAttribute=\"centerY\" secondItem=\"Xuz-Uo-wO2\" secondAttribute=\"centerY\" id=\"Qtt-YQ-m1C\"/>\n                                                    <constraint firstItem=\"wGa-S6-kGM\" firstAttribute=\"centerX\" secondItem=\"Xuz-Uo-wO2\" secondAttribute=\"centerX\" id=\"yye-Q9-mxT\"/>\n                                                </constraints>\n                                                <connections>\n                                                    <outlet property=\"checkboxButton\" destination=\"wGa-S6-kGM\" id=\"ZC6-HL-33p\"/>\n                                                </connections>\n                                            </tableCellView>\n                                        </prototypeCellViews>\n                                    </tableColumn>\n                                    <tableColumn identifier=\"valueColumn\" width=\"629\" minWidth=\"40\" maxWidth=\"1000\" id=\"5DX-CP-hGY\">\n                                        <tableHeaderCell key=\"headerCell\" lineBreakMode=\"truncatingTail\" borderStyle=\"border\" title=\"Description\">\n                                            <color key=\"textColor\" name=\"headerTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                            <color key=\"backgroundColor\" name=\"headerColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                        </tableHeaderCell>\n                                        <textFieldCell key=\"dataCell\" lineBreakMode=\"truncatingTail\" selectable=\"YES\" editable=\"YES\" title=\"Text Cell\" id=\"582-Fa-Lf4\">\n                                            <font key=\"font\" metaFont=\"system\"/>\n                                            <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                            <color key=\"backgroundColor\" name=\"controlBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                        </textFieldCell>\n                                        <tableColumnResizingMask key=\"resizingMask\" resizeWithTable=\"YES\"/>\n                                        <prototypeCellViews>\n                                            <tableCellView identifier=\"valueColumnCell\" id=\"sPv-Lx-coN\" customClass=\"DescriptionCellView\" customModule=\"Aerial\" customModuleProvider=\"target\">\n                                                <rect key=\"frame\" x=\"73.248931931094376\" y=\"0.0\" width=\"629\" height=\"68\"/>\n                                                <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                                                <subviews>\n                                                    <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"k0S-C5-p57\">\n                                                        <rect key=\"frame\" x=\"0.0\" y=\"50\" width=\"38\" height=\"16\"/>\n                                                        <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"Label\" id=\"t3l-WH-Xr4\">\n                                                            <font key=\"font\" metaFont=\"systemMedium\" size=\"13\"/>\n                                                            <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                            <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                        </textFieldCell>\n                                                    </textField>\n                                                    <textField verticalHuggingPriority=\"750\" horizontalCompressionResistancePriority=\"250\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"PiP-K7-e2O\">\n                                                        <rect key=\"frame\" x=\"0.0\" y=\"22\" width=\"629\" height=\"28\"/>\n                                                        <textFieldCell key=\"cell\" id=\"FjG-vS-zA3\">\n                                                            <font key=\"font\" metaFont=\"smallSystem\"/>\n                                                            <string key=\"title\">Multiline Label\nline2</string>\n                                                            <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                            <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                        </textFieldCell>\n                                                    </textField>\n                                                    <imageView horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"OZC-3S-Mp4\">\n                                                        <rect key=\"frame\" x=\"2\" y=\"3\" width=\"16\" height=\"16\"/>\n                                                        <constraints>\n                                                            <constraint firstAttribute=\"height\" constant=\"16\" id=\"MH8-e1-tdb\"/>\n                                                            <constraint firstAttribute=\"width\" constant=\"16\" id=\"R6w-jm-C7T\"/>\n                                                        </constraints>\n                                                        <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" image=\"film\" id=\"1rB-mU-MYO\"/>\n                                                    </imageView>\n                                                    <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"kAu-1v-NWK\">\n                                                        <rect key=\"frame\" x=\"549\" y=\"4\" width=\"80\" height=\"14\"/>\n                                                        <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" alignment=\"right\" title=\"Last updated: \" id=\"q9w-ij-mAW\">\n                                                            <font key=\"font\" metaFont=\"smallSystem\"/>\n                                                            <color key=\"textColor\" name=\"secondaryLabelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                            <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                        </textFieldCell>\n                                                    </textField>\n                                                    <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" horizontalCompressionResistancePriority=\"10\" verticalCompressionResistancePriority=\"10\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Ral-81-onK\">\n                                                        <rect key=\"frame\" x=\"20\" y=\"4\" width=\"56\" height=\"14\"/>\n                                                        <textFieldCell key=\"cell\" lineBreakMode=\"truncatingTail\" alignment=\"left\" title=\"69 videos\" usesSingleLineMode=\"YES\" id=\"GdW-Ad-2Dd\">\n                                                            <font key=\"font\" metaFont=\"smallSystem\"/>\n                                                            <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                            <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                        </textFieldCell>\n                                                    </textField>\n                                                    <stackView distribution=\"fill\" orientation=\"horizontal\" alignment=\"bottom\" spacing=\"0.0\" horizontalStackHuggingPriority=\"249.99998474121094\" verticalStackHuggingPriority=\"249.99998474121094\" detachesHiddenViews=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"qTw-Wg-fqd\">\n                                                        <rect key=\"frame\" x=\"495\" y=\"46\" width=\"132\" height=\"20\"/>\n                                                        <subviews>\n                                                            <imageView toolTip=\"Nature\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"gCH-fr-qvu\">\n                                                                <rect key=\"frame\" x=\"0.0\" y=\"1\" width=\"20\" height=\"18\"/>\n                                                                <constraints>\n                                                                    <constraint firstAttribute=\"height\" constant=\"18\" id=\"Mzw-vZ-mzz\"/>\n                                                                    <constraint firstAttribute=\"width\" constant=\"20\" id=\"ziG-x5-MNt\"/>\n                                                                </constraints>\n                                                                <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" image=\"flame\" id=\"PiW-qG-Zd3\"/>\n                                                            </imageView>\n                                                            <imageView toolTip=\"City\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"fnJ-n1-Vw6\">\n                                                                <rect key=\"frame\" x=\"20\" y=\"0.0\" width=\"20\" height=\"20\"/>\n                                                                <constraints>\n                                                                    <constraint firstAttribute=\"width\" constant=\"20\" id=\"81x-IA-q6S\"/>\n                                                                    <constraint firstAttribute=\"height\" constant=\"20\" id=\"rNw-P3-qTo\"/>\n                                                                </constraints>\n                                                                <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" image=\"tram.fill\" id=\"jx0-o7-kDW\"/>\n                                                            </imageView>\n                                                            <imageView toolTip=\"Space\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"tUg-uk-dHW\">\n                                                                <rect key=\"frame\" x=\"40\" y=\"0.0\" width=\"20\" height=\"20\"/>\n                                                                <constraints>\n                                                                    <constraint firstAttribute=\"width\" constant=\"20\" id=\"3fi-bF-EQS\"/>\n                                                                    <constraint firstAttribute=\"height\" constant=\"20\" id=\"6JU-Ni-yQ9\"/>\n                                                                </constraints>\n                                                                <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" image=\"sparkles\" id=\"yRH-Fz-X4f\"/>\n                                                            </imageView>\n                                                            <imageView toolTip=\"Sea\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"kZQ-Pd-nPL\">\n                                                                <rect key=\"frame\" x=\"60\" y=\"0.0\" width=\"24\" height=\"20\"/>\n                                                                <constraints>\n                                                                    <constraint firstAttribute=\"height\" constant=\"20\" id=\"jAe-Oj-jwm\"/>\n                                                                    <constraint firstAttribute=\"width\" constant=\"24\" id=\"jdh-kp-Wcn\"/>\n                                                                </constraints>\n                                                                <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" image=\"helm\" id=\"awM-JR-hZe\"/>\n                                                            </imageView>\n                                                            <imageView toolTip=\"Beach\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"3hx-vw-BFg\">\n                                                                <rect key=\"frame\" x=\"84\" y=\"0.0\" width=\"24\" height=\"20\"/>\n                                                                <constraints>\n                                                                    <constraint firstAttribute=\"width\" constant=\"24\" id=\"9y1-zA-8yo\"/>\n                                                                    <constraint firstAttribute=\"height\" constant=\"20\" id=\"L1e-cW-4V2\"/>\n                                                                </constraints>\n                                                                <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" image=\"helm\" id=\"MRm-4P-OX2\"/>\n                                                            </imageView>\n                                                            <imageView toolTip=\"Countryside\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"63F-uv-Hra\">\n                                                                <rect key=\"frame\" x=\"108\" y=\"0.0\" width=\"24\" height=\"20\"/>\n                                                                <constraints>\n                                                                    <constraint firstAttribute=\"width\" constant=\"24\" id=\"CYU-d8-SkW\"/>\n                                                                    <constraint firstAttribute=\"height\" constant=\"20\" id=\"X5y-Tz-Kut\"/>\n                                                                </constraints>\n                                                                <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" image=\"helm\" id=\"DJ7-Xa-ls9\"/>\n                                                            </imageView>\n                                                        </subviews>\n                                                        <constraints>\n                                                            <constraint firstItem=\"gCH-fr-qvu\" firstAttribute=\"top\" secondItem=\"qTw-Wg-fqd\" secondAttribute=\"top\" constant=\"1\" id=\"Qc6-Ze-xLb\"/>\n                                                        </constraints>\n                                                        <visibilityPriorities>\n                                                            <integer value=\"1000\"/>\n                                                            <integer value=\"1000\"/>\n                                                            <integer value=\"1000\"/>\n                                                            <integer value=\"1000\"/>\n                                                            <integer value=\"1000\"/>\n                                                            <integer value=\"1000\"/>\n                                                        </visibilityPriorities>\n                                                        <customSpacing>\n                                                            <real value=\"3.4028234663852886e+38\"/>\n                                                            <real value=\"3.4028234663852886e+38\"/>\n                                                            <real value=\"3.4028234663852886e+38\"/>\n                                                            <real value=\"3.4028234663852886e+38\"/>\n                                                            <real value=\"3.4028234663852886e+38\"/>\n                                                            <real value=\"3.4028234663852886e+38\"/>\n                                                        </customSpacing>\n                                                    </stackView>\n                                                    <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"DR3-H7-D3b\">\n                                                        <rect key=\"frame\" x=\"373\" y=\"2\" width=\"82\" height=\"18\"/>\n                                                        <buttonCell key=\"cell\" type=\"inline\" title=\"View License\" bezelStyle=\"inline\" alignment=\"center\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"Ev0-LD-rjW\">\n                                                            <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                                                            <font key=\"font\" metaFont=\"smallSystemBold\"/>\n                                                        </buttonCell>\n                                                        <connections>\n                                                            <action selector=\"licenseButtonClick:\" target=\"sPv-Lx-coN\" id=\"zIA-o3-aS6\"/>\n                                                        </connections>\n                                                    </button>\n                                                    <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"fLV-KX-lp1\">\n                                                        <rect key=\"frame\" x=\"316\" y=\"2\" width=\"49\" height=\"18\"/>\n                                                        <buttonCell key=\"cell\" type=\"inline\" title=\"More...\" bezelStyle=\"inline\" alignment=\"center\" borderStyle=\"border\" inset=\"2\" id=\"9KC-Rc-HHK\">\n                                                            <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                                                            <font key=\"font\" metaFont=\"smallSystemBold\"/>\n                                                        </buttonCell>\n                                                        <connections>\n                                                            <action selector=\"moreButtonClick:\" target=\"sPv-Lx-coN\" id=\"lqG-Uq-p0o\"/>\n                                                        </connections>\n                                                    </button>\n                                                    <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Wbg-Ju-sA9\">\n                                                        <rect key=\"frame\" x=\"463\" y=\"2\" width=\"80\" height=\"18\"/>\n                                                        <buttonCell key=\"cell\" type=\"inline\" title=\"Refresh Now\" bezelStyle=\"inline\" alignment=\"center\" borderStyle=\"border\" inset=\"2\" id=\"oT9-DN-3Gm\">\n                                                            <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                                                            <font key=\"font\" metaFont=\"smallSystemBold\"/>\n                                                        </buttonCell>\n                                                        <connections>\n                                                            <action selector=\"refreshNowButtonClick:\" target=\"sPv-Lx-coN\" id=\"vT7-vl-uoO\"/>\n                                                        </connections>\n                                                    </button>\n                                                </subviews>\n                                                <constraints>\n                                                    <constraint firstItem=\"Ral-81-onK\" firstAttribute=\"leading\" secondItem=\"OZC-3S-Mp4\" secondAttribute=\"trailing\" constant=\"4\" id=\"1c3-cT-hOG\"/>\n                                                    <constraint firstAttribute=\"trailing\" secondItem=\"kAu-1v-NWK\" secondAttribute=\"trailing\" constant=\"2\" id=\"25i-gZ-MgC\"/>\n                                                    <constraint firstItem=\"k0S-C5-p57\" firstAttribute=\"leading\" secondItem=\"sPv-Lx-coN\" secondAttribute=\"leading\" constant=\"2\" id=\"Caa-cg-8Ro\"/>\n                                                    <constraint firstItem=\"PiP-K7-e2O\" firstAttribute=\"leading\" secondItem=\"sPv-Lx-coN\" secondAttribute=\"leading\" constant=\"2\" id=\"Cyd-bm-njq\"/>\n                                                    <constraint firstAttribute=\"trailing\" secondItem=\"qTw-Wg-fqd\" secondAttribute=\"trailing\" constant=\"2\" id=\"DAA-XC-bru\"/>\n                                                    <constraint firstItem=\"kAu-1v-NWK\" firstAttribute=\"firstBaseline\" secondItem=\"DR3-H7-D3b\" secondAttribute=\"firstBaseline\" id=\"EaS-Nn-ZvK\"/>\n                                                    <constraint firstItem=\"k0S-C5-p57\" firstAttribute=\"top\" secondItem=\"sPv-Lx-coN\" secondAttribute=\"top\" constant=\"2\" id=\"Eb3-Od-yPr\"/>\n                                                    <constraint firstAttribute=\"bottom\" secondItem=\"kAu-1v-NWK\" secondAttribute=\"bottom\" constant=\"4\" id=\"Gds-WC-UaW\"/>\n                                                    <constraint firstItem=\"DR3-H7-D3b\" firstAttribute=\"leading\" secondItem=\"fLV-KX-lp1\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"Hgl-eh-wVa\"/>\n                                                    <constraint firstItem=\"fLV-KX-lp1\" firstAttribute=\"leading\" relation=\"greaterThanOrEqual\" secondItem=\"Ral-81-onK\" secondAttribute=\"trailing\" constant=\"8\" id=\"JjP-Dw-Uwz\"/>\n                                                    <constraint firstItem=\"PiP-K7-e2O\" firstAttribute=\"top\" secondItem=\"k0S-C5-p57\" secondAttribute=\"bottom\" id=\"Pom-1r-tiY\"/>\n                                                    <constraint firstItem=\"fLV-KX-lp1\" firstAttribute=\"firstBaseline\" secondItem=\"Wbg-Ju-sA9\" secondAttribute=\"firstBaseline\" id=\"Yde-f8-hPo\"/>\n                                                    <constraint firstAttribute=\"bottom\" secondItem=\"OZC-3S-Mp4\" secondAttribute=\"bottom\" constant=\"3\" id=\"f99-lA-C33\"/>\n                                                    <constraint firstItem=\"kAu-1v-NWK\" firstAttribute=\"leading\" secondItem=\"Wbg-Ju-sA9\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"fPJ-EV-DmY\"/>\n                                                    <constraint firstAttribute=\"bottom\" secondItem=\"Ral-81-onK\" secondAttribute=\"bottom\" constant=\"4\" id=\"hwX-ds-L1b\"/>\n                                                    <constraint firstAttribute=\"trailing\" secondItem=\"PiP-K7-e2O\" secondAttribute=\"trailing\" constant=\"2\" id=\"lFC-NG-qwj\"/>\n                                                    <constraint firstItem=\"OZC-3S-Mp4\" firstAttribute=\"leading\" secondItem=\"sPv-Lx-coN\" secondAttribute=\"leading\" constant=\"2\" id=\"nKa-TD-7I5\"/>\n                                                    <constraint firstItem=\"Wbg-Ju-sA9\" firstAttribute=\"leading\" secondItem=\"DR3-H7-D3b\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"nmX-0y-4OE\"/>\n                                                    <constraint firstItem=\"qTw-Wg-fqd\" firstAttribute=\"top\" secondItem=\"sPv-Lx-coN\" secondAttribute=\"top\" constant=\"2\" id=\"sfI-V9-81N\"/>\n                                                    <constraint firstItem=\"DR3-H7-D3b\" firstAttribute=\"firstBaseline\" secondItem=\"fLV-KX-lp1\" secondAttribute=\"firstBaseline\" id=\"wva-dh-lfK\"/>\n                                                </constraints>\n                                                <connections>\n                                                    <outlet property=\"descriptionLabel\" destination=\"PiP-K7-e2O\" id=\"tsz-p2-uFp\"/>\n                                                    <outlet property=\"imageFilm\" destination=\"OZC-3S-Mp4\" id=\"mua-iD-edL\"/>\n                                                    <outlet property=\"imageScene1\" destination=\"gCH-fr-qvu\" id=\"FPG-kt-mMD\"/>\n                                                    <outlet property=\"imageScene2\" destination=\"fnJ-n1-Vw6\" id=\"J4i-Xq-IjR\"/>\n                                                    <outlet property=\"imageScene3\" destination=\"tUg-uk-dHW\" id=\"0qe-8p-UQi\"/>\n                                                    <outlet property=\"imageScene4\" destination=\"kZQ-Pd-nPL\" id=\"GO5-eb-MkI\"/>\n                                                    <outlet property=\"imageScene5\" destination=\"3hx-vw-BFg\" id=\"UIt-07-H9i\"/>\n                                                    <outlet property=\"imageScene6\" destination=\"63F-uv-Hra\" id=\"bkU-Ua-LGh\"/>\n                                                    <outlet property=\"lastUpdatedLabel\" destination=\"kAu-1v-NWK\" id=\"88h-wu-ytq\"/>\n                                                    <outlet property=\"licenseButton\" destination=\"DR3-H7-D3b\" id=\"eWr-Dk-ubL\"/>\n                                                    <outlet property=\"moreButton\" destination=\"fLV-KX-lp1\" id=\"36f-Z0-AGc\"/>\n                                                    <outlet property=\"refreshNowButton\" destination=\"Wbg-Ju-sA9\" id=\"16b-Sc-ZK5\"/>\n                                                    <outlet property=\"titleLabel\" destination=\"k0S-C5-p57\" id=\"fne-gL-EWM\"/>\n                                                    <outlet property=\"videoCount\" destination=\"Ral-81-onK\" id=\"yhA-Kk-fpg\"/>\n                                                </connections>\n                                            </tableCellView>\n                                        </prototypeCellViews>\n                                    </tableColumn>\n                                    <tableColumn identifier=\"actionColumn\" width=\"64\" minWidth=\"64\" maxWidth=\"64\" id=\"BRw-aR-oDG\">\n                                        <tableHeaderCell key=\"headerCell\" lineBreakMode=\"truncatingTail\" borderStyle=\"border\" alignment=\"left\" title=\"Action\">\n                                            <color key=\"textColor\" name=\"headerTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                            <color key=\"backgroundColor\" white=\"0.0\" alpha=\"0.0\" colorSpace=\"custom\" customColorSpace=\"genericGamma22GrayColorSpace\"/>\n                                        </tableHeaderCell>\n                                        <textFieldCell key=\"dataCell\" lineBreakMode=\"truncatingTail\" selectable=\"YES\" editable=\"YES\" alignment=\"left\" title=\"Text Cell\" id=\"MDA-gq-Dpy\">\n                                            <font key=\"font\" metaFont=\"system\"/>\n                                            <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                            <color key=\"backgroundColor\" name=\"controlBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                        </textFieldCell>\n                                        <prototypeCellViews>\n                                            <tableCellView id=\"TlS-Vu-nlh\" customClass=\"ActionCellView\" customModule=\"Aerial\" customModuleProvider=\"target\">\n                                                <rect key=\"frame\" x=\"719.49786386218875\" y=\"0.0\" width=\"61\" height=\"68\"/>\n                                                <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                                                <subviews>\n                                                    <button toolTip=\"Download videos from this source now\" id=\"dhO-VP-Rzn\">\n                                                        <rect key=\"frame\" x=\"14\" y=\"16\" width=\"32\" height=\"38\"/>\n                                                        <autoresizingMask key=\"autoresizingMask\"/>\n                                                        <buttonCell key=\"cell\" type=\"square\" bezelStyle=\"shadowlessSquare\" image=\"NSTouchBarDownloadTemplate\" imagePosition=\"only\" alignment=\"center\" imageScaling=\"proportionallyUpOrDown\" inset=\"2\" id=\"J6u-eW-Yaw\">\n                                                            <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                                                            <font key=\"font\" metaFont=\"system\"/>\n                                                        </buttonCell>\n                                                        <connections>\n                                                            <action selector=\"actionButton:\" target=\"TlS-Vu-nlh\" id=\"kdr-tI-Urk\"/>\n                                                        </connections>\n                                                    </button>\n                                                    <progressIndicator fixedFrame=\"YES\" maxValue=\"100\" indeterminate=\"YES\" controlSize=\"small\" style=\"spinning\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"8fH-Cw-pf2\">\n                                                        <rect key=\"frame\" x=\"22\" y=\"26\" width=\"16\" height=\"16\"/>\n                                                        <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                                                    </progressIndicator>\n                                                </subviews>\n                                                <connections>\n                                                    <outlet property=\"actionButton\" destination=\"dhO-VP-Rzn\" id=\"5gW-VN-T1M\"/>\n                                                    <outlet property=\"spinner\" destination=\"8fH-Cw-pf2\" id=\"GlZ-He-jhS\"/>\n                                                </connections>\n                                            </tableCellView>\n                                        </prototypeCellViews>\n                                    </tableColumn>\n                                </tableColumns>\n                            </outlineView>\n                        </subviews>\n                    </clipView>\n                    <scroller key=\"horizontalScroller\" hidden=\"YES\" wantsLayer=\"YES\" verticalHuggingPriority=\"750\" doubleValue=\"1\" horizontal=\"YES\" id=\"Zsv-hH-lq4\">\n                        <rect key=\"frame\" x=\"-100\" y=\"-100\" width=\"750\" height=\"16\"/>\n                        <autoresizingMask key=\"autoresizingMask\"/>\n                    </scroller>\n                    <scroller key=\"verticalScroller\" hidden=\"YES\" wantsLayer=\"YES\" verticalHuggingPriority=\"750\" horizontal=\"NO\" id=\"xTB-id-9r0\">\n                        <rect key=\"frame\" x=\"224\" y=\"17\" width=\"15\" height=\"102\"/>\n                        <autoresizingMask key=\"autoresizingMask\"/>\n                    </scroller>\n                    <tableHeaderView key=\"headerView\" wantsLayer=\"YES\" id=\"b1V-rc-xZQ\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"790\" height=\"25\"/>\n                        <autoresizingMask key=\"autoresizingMask\"/>\n                    </tableHeaderView>\n                </scrollView>\n                <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"YCA-Kf-OqL\">\n                    <rect key=\"frame\" x=\"10\" y=\"14\" width=\"129\" height=\"40\"/>\n                    <buttonCell key=\"cell\" type=\"push\" title=\"Add Local...\" bezelStyle=\"rounded\" image=\"folder\" catalog=\"system\" imagePosition=\"leading\" alignment=\"center\" controlSize=\"large\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"M9G-4n-Orj\">\n                        <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"addLocalClick:\" target=\"-2\" id=\"qwA-Tu-7E3\"/>\n                    </connections>\n                </button>\n                <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"H7z-UB-Yzx\">\n                    <rect key=\"frame\" x=\"147\" y=\"14\" width=\"134\" height=\"40\"/>\n                    <buttonCell key=\"cell\" type=\"push\" title=\"Add Online...\" bezelStyle=\"rounded\" image=\"antenna.radiowaves.left.and.right\" catalog=\"system\" imagePosition=\"leading\" alignment=\"center\" controlSize=\"large\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"Nc1-j7-Z9R\">\n                        <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"addOnlineClick:\" target=\"-2\" id=\"Xre-aK-0mV\"/>\n                    </connections>\n                </button>\n                <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"hJ0-L4-qoE\">\n                    <rect key=\"frame\" x=\"289\" y=\"14\" width=\"173\" height=\"40\"/>\n                    <buttonCell key=\"cell\" type=\"push\" title=\"Get More Videos...\" bezelStyle=\"rounded\" image=\"cloud\" catalog=\"system\" imagePosition=\"leading\" alignment=\"center\" controlSize=\"large\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"Yg6-pt-6h6\">\n                        <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"getMoreVideosClick:\" target=\"-2\" id=\"OrA-Hw-xN8\"/>\n                    </connections>\n                </button>\n                <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"P2e-fe-Js2\">\n                    <rect key=\"frame\" x=\"618\" y=\"14\" width=\"185\" height=\"40\"/>\n                    <buttonCell key=\"cell\" type=\"push\" title=\"Download All Videos\" bezelStyle=\"rounded\" image=\"book\" catalog=\"system\" imagePosition=\"leading\" alignment=\"center\" controlSize=\"large\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"dsu-LI-sTF\">\n                        <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"downloadAllClick:\" target=\"-2\" id=\"Yfd-DG-sxX\"/>\n                    </connections>\n                </button>\n                <progressIndicator maxValue=\"100\" indeterminate=\"YES\" controlSize=\"small\" style=\"spinning\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"heQ-Ra-4Qf\">\n                    <rect key=\"frame\" x=\"600\" y=\"26\" width=\"16\" height=\"16\"/>\n                </progressIndicator>\n                <popUpButton verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"FxS-MX-bfw\">\n                    <rect key=\"frame\" x=\"699\" y=\"484\" width=\"103\" height=\"40\"/>\n                    <popUpButtonCell key=\"cell\" type=\"push\" title=\"Weekly\" bezelStyle=\"rounded\" alignment=\"left\" controlSize=\"large\" lineBreakMode=\"truncatingTail\" state=\"on\" borderStyle=\"borderAndBezel\" toolTip=\"How often should Aerial looks for new content?\" imageScaling=\"proportionallyDown\" inset=\"2\" selectedItem=\"TTP-0V-RTm\" id=\"h9e-Et-eu5\">\n                        <behavior key=\"behavior\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <menu key=\"menu\" id=\"PRc-jj-Fl7\">\n                            <items>\n                                <menuItem title=\"Weekly\" state=\"on\" id=\"TTP-0V-RTm\" userLabel=\"Weekly\"/>\n                                <menuItem title=\"Monthly\" id=\"v6w-Uv-FgE\" userLabel=\"Monthly\"/>\n                                <menuItem title=\"Never\" id=\"2SY-Eu-cGv\" userLabel=\"Never\"/>\n                            </items>\n                        </menu>\n                    </popUpButtonCell>\n                    <connections>\n                        <action selector=\"refreshPeriodicityChange:\" target=\"-2\" id=\"hUi-fS-Wye\"/>\n                    </connections>\n                </popUpButton>\n                <textField toolTip=\"How often should Aerial looks for new content?\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"HWL-LY-Ozg\">\n                    <rect key=\"frame\" x=\"640\" y=\"497\" width=\"58\" height=\"17\"/>\n                    <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"Refresh:\" id=\"8uC-gE-Cn4\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <imageView horizontalHuggingPriority=\"25\" verticalHuggingPriority=\"25\" horizontalCompressionResistancePriority=\"75\" verticalCompressionResistancePriority=\"75\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"cPn-il-E6e\">\n                    <rect key=\"frame\" x=\"16\" y=\"487.5\" width=\"28\" height=\"32\"/>\n                    <constraints>\n                        <constraint firstAttribute=\"width\" constant=\"28\" id=\"NPY-Pt-yuk\"/>\n                    </constraints>\n                    <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyUpOrDown\" id=\"VO6-l5-plS\">\n                        <imageReference key=\"image\" image=\"antenna.radiowaves.left.and.right\" catalog=\"system\" symbolScale=\"large\"/>\n                    </imageCell>\n                    <color key=\"contentTintColor\" name=\"controlAccentColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                </imageView>\n                <textField horizontalCompressionResistancePriority=\"250\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"8Bi-xK-lN6\">\n                    <rect key=\"frame\" x=\"52\" y=\"497\" width=\"316\" height=\"17\"/>\n                    <textFieldCell key=\"cell\" selectable=\"YES\" title=\"You can add videos from your Mac, or check our\" id=\"0AG-cL-NaN\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"5gs-GK-DV1\">\n                    <rect key=\"frame\" x=\"368\" y=\"484\" width=\"140\" height=\"40\"/>\n                    <buttonCell key=\"cell\" type=\"push\" title=\"online repository\" bezelStyle=\"rounded\" alignment=\"center\" controlSize=\"large\" state=\"on\" borderStyle=\"border\" inset=\"2\" id=\"UHp-fo-X9a\">\n                        <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"getMoreVideosClick:\" target=\"-2\" id=\"eg6-eU-5b8\"/>\n                    </connections>\n                </button>\n            </subviews>\n            <constraints>\n                <constraint firstAttribute=\"trailing\" secondItem=\"FxS-MX-bfw\" secondAttribute=\"trailing\" constant=\"16\" id=\"0n0-Ql-Jkr\"/>\n                <constraint firstItem=\"cPn-il-E6e\" firstAttribute=\"leading\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"leading\" constant=\"16\" id=\"3Nz-UK-Se0\"/>\n                <constraint firstItem=\"bBq-pn-VQA\" firstAttribute=\"top\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"top\" constant=\"54\" id=\"AxL-RL-dl4\"/>\n                <constraint firstAttribute=\"trailing\" secondItem=\"bBq-pn-VQA\" secondAttribute=\"trailing\" constant=\"16\" id=\"CEW-pk-n39\"/>\n                <constraint firstItem=\"FxS-MX-bfw\" firstAttribute=\"leading\" secondItem=\"HWL-LY-Ozg\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"Gdm-Os-9c9\"/>\n                <constraint firstItem=\"bBq-pn-VQA\" firstAttribute=\"top\" secondItem=\"cPn-il-E6e\" secondAttribute=\"bottom\" constant=\"16\" id=\"Hm7-kb-6ce\"/>\n                <constraint firstItem=\"bBq-pn-VQA\" firstAttribute=\"leading\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"leading\" constant=\"16\" id=\"JDq-eI-FdT\"/>\n                <constraint firstItem=\"5gs-GK-DV1\" firstAttribute=\"top\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"top\" constant=\"12\" id=\"LJC-ju-YML\"/>\n                <constraint firstItem=\"P2e-fe-Js2\" firstAttribute=\"leading\" secondItem=\"heQ-Ra-4Qf\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"OCb-b9-Dor\"/>\n                <constraint firstItem=\"hJ0-L4-qoE\" firstAttribute=\"leading\" secondItem=\"H7z-UB-Yzx\" secondAttribute=\"trailing\" constant=\"20\" id=\"OZp-Te-bft\"/>\n                <constraint firstItem=\"hJ0-L4-qoE\" firstAttribute=\"firstBaseline\" secondItem=\"H7z-UB-Yzx\" secondAttribute=\"firstBaseline\" id=\"PUI-mu-CC0\"/>\n                <constraint firstItem=\"5gs-GK-DV1\" firstAttribute=\"firstBaseline\" secondItem=\"8Bi-xK-lN6\" secondAttribute=\"firstBaseline\" id=\"Umu-mo-HsS\"/>\n                <constraint firstAttribute=\"bottom\" secondItem=\"bBq-pn-VQA\" secondAttribute=\"bottom\" constant=\"68\" id=\"VCk-gB-2eO\"/>\n                <constraint firstItem=\"P2e-fe-Js2\" firstAttribute=\"centerY\" secondItem=\"heQ-Ra-4Qf\" secondAttribute=\"centerY\" id=\"VcU-vI-t0W\"/>\n                <constraint firstAttribute=\"height\" relation=\"greaterThanOrEqual\" constant=\"530\" id=\"W4O-8Q-5Ss\"/>\n                <constraint firstAttribute=\"width\" relation=\"greaterThanOrEqual\" constant=\"811\" id=\"WEp-mk-3VN\"/>\n                <constraint firstAttribute=\"bottom\" secondItem=\"H7z-UB-Yzx\" secondAttribute=\"bottom\" constant=\"20\" id=\"ZvC-kw-2bu\"/>\n                <constraint firstItem=\"FxS-MX-bfw\" firstAttribute=\"top\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"top\" constant=\"12\" id=\"bhN-QM-UW3\"/>\n                <constraint firstAttribute=\"bottom\" secondItem=\"P2e-fe-Js2\" secondAttribute=\"bottom\" constant=\"20\" symbolic=\"YES\" id=\"gxV-PO-dFv\"/>\n                <constraint firstItem=\"cPn-il-E6e\" firstAttribute=\"top\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"top\" constant=\"16\" id=\"hxo-R2-4Rm\"/>\n                <constraint firstItem=\"YCA-Kf-OqL\" firstAttribute=\"leading\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"leading\" constant=\"16\" id=\"mgC-7f-Ojl\"/>\n                <constraint firstItem=\"8Bi-xK-lN6\" firstAttribute=\"leading\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"leading\" constant=\"54\" id=\"mm3-tA-48J\"/>\n                <constraint firstAttribute=\"trailing\" secondItem=\"P2e-fe-Js2\" secondAttribute=\"trailing\" constant=\"16\" id=\"mqJ-bM-r51\"/>\n                <constraint firstItem=\"bBq-pn-VQA\" firstAttribute=\"centerX\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"centerX\" id=\"o3Q-R6-ddi\"/>\n                <constraint firstItem=\"FxS-MX-bfw\" firstAttribute=\"firstBaseline\" secondItem=\"HWL-LY-Ozg\" secondAttribute=\"firstBaseline\" id=\"qeL-3X-smB\"/>\n                <constraint firstItem=\"5gs-GK-DV1\" firstAttribute=\"leading\" secondItem=\"8Bi-xK-lN6\" secondAttribute=\"trailing\" constant=\"8\" id=\"t8d-m0-yFb\"/>\n                <constraint firstItem=\"H7z-UB-Yzx\" firstAttribute=\"leading\" secondItem=\"YCA-Kf-OqL\" secondAttribute=\"trailing\" constant=\"20\" id=\"vti-sF-9wr\"/>\n                <constraint firstAttribute=\"bottom\" secondItem=\"YCA-Kf-OqL\" secondAttribute=\"bottom\" constant=\"20\" id=\"z1F-O9-1kK\"/>\n            </constraints>\n            <point key=\"canvasLocation\" x=\"-183.5\" y=\"820.5\"/>\n        </customView>\n        <window title=\"Add an Online Source\" allowsToolTipsWhenApplicationIsInactive=\"NO\" autorecalculatesKeyViewLoop=\"NO\" restorable=\"NO\" releasedWhenClosed=\"NO\" visibleAtLaunch=\"NO\" frameAutosaveName=\"\" animationBehavior=\"default\" id=\"iB7-4m-6mH\">\n            <windowStyleMask key=\"styleMask\" titled=\"YES\" closable=\"YES\"/>\n            <rect key=\"contentRect\" x=\"283\" y=\"305\" width=\"753\" height=\"157\"/>\n            <rect key=\"screenRect\" x=\"0.0\" y=\"0.0\" width=\"2560\" height=\"1415\"/>\n            <view key=\"contentView\" ambiguous=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Ek0-xw-cVO\">\n                <rect key=\"frame\" x=\"0.0\" y=\"12\" width=\"740\" height=\"145\"/>\n                <subviews>\n                    <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"oit-Js-Fye\">\n                        <rect key=\"frame\" x=\"18\" y=\"109\" width=\"352\" height=\"16\"/>\n                        <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"Please paste the URL of your online Aerial source below : \" id=\"iQW-jI-Mm5\">\n                            <font key=\"font\" usesAppearanceFont=\"YES\"/>\n                            <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                            <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        </textFieldCell>\n                    </textField>\n                    <textField verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"gxJ-4P-fMD\">\n                        <rect key=\"frame\" x=\"20\" y=\"68\" width=\"700\" height=\"21\"/>\n                        <constraints>\n                            <constraint firstAttribute=\"width\" constant=\"700\" id=\"V73-Uq-dkJ\"/>\n                        </constraints>\n                        <textFieldCell key=\"cell\" controlSize=\"large\" scrollable=\"YES\" lineBreakMode=\"clipping\" selectable=\"YES\" editable=\"YES\" sendsActionOnEndEditing=\"YES\" borderStyle=\"bezel\" placeholderString=\"https://example.com/aerialvideos/\" drawsBackground=\"YES\" usesSingleLineMode=\"YES\" id=\"itG-OB-VSe\">\n                            <font key=\"font\" metaFont=\"system\"/>\n                            <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                            <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        </textFieldCell>\n                    </textField>\n                    <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"b1p-kF-lsq\">\n                        <rect key=\"frame\" x=\"570\" y=\"14\" width=\"77\" height=\"40\"/>\n                        <buttonCell key=\"cell\" type=\"push\" title=\"Cancel\" bezelStyle=\"rounded\" alignment=\"center\" controlSize=\"large\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"RQq-xj-vRk\">\n                            <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                            <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        </buttonCell>\n                        <connections>\n                            <action selector=\"addOnlineCancel:\" target=\"-2\" id=\"w3I-Gu-58Y\"/>\n                        </connections>\n                    </button>\n                    <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"PuX-0t-vmu\">\n                        <rect key=\"frame\" x=\"50\" y=\"24\" width=\"269\" height=\"16\"/>\n                        <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                        <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"This is only for Aerial specific video sources\" id=\"TZ8-kc-1VB\">\n                            <font key=\"font\" usesAppearanceFont=\"YES\"/>\n                            <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                            <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        </textFieldCell>\n                    </textField>\n                    <imageView horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"MWk-On-UvL\">\n                        <rect key=\"frame\" x=\"20\" y=\"20\" width=\"24\" height=\"24\"/>\n                        <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                        <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" image=\"NSCaution\" id=\"V9e-KD-JHL\"/>\n                    </imageView>\n                    <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Sxx-N6-QgG\">\n                        <rect key=\"frame\" x=\"655\" y=\"14\" width=\"71\" height=\"40\"/>\n                        <buttonCell key=\"cell\" type=\"push\" title=\"Install\" bezelStyle=\"rounded\" alignment=\"center\" controlSize=\"large\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"Q0Q-DA-siQ\">\n                            <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                            <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        </buttonCell>\n                        <connections>\n                            <action selector=\"addOnlineDownload:\" target=\"-2\" id=\"4Oe-ld-UIO\"/>\n                        </connections>\n                    </button>\n                    <button verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Xfv-hg-zUZ\">\n                        <rect key=\"frame\" x=\"319\" y=\"11\" width=\"145\" height=\"40\"/>\n                        <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                        <buttonCell key=\"cell\" type=\"push\" title=\"Find More Videos\" bezelStyle=\"rounded\" alignment=\"center\" controlSize=\"large\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"vA5-Sg-TQe\">\n                            <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                            <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        </buttonCell>\n                        <connections>\n                            <action selector=\"findMoreVideos:\" target=\"-2\" id=\"oTx-yp-BzV\"/>\n                        </connections>\n                    </button>\n                </subviews>\n                <constraints>\n                    <constraint firstItem=\"Sxx-N6-QgG\" firstAttribute=\"leading\" secondItem=\"b1p-kF-lsq\" secondAttribute=\"trailing\" constant=\"20\" id=\"6Jx-w1-QwA\"/>\n                    <constraint firstAttribute=\"bottom\" secondItem=\"Sxx-N6-QgG\" secondAttribute=\"bottom\" constant=\"20\" id=\"6Kb-JM-27i\"/>\n                    <constraint firstItem=\"oit-Js-Fye\" firstAttribute=\"leading\" secondItem=\"Ek0-xw-cVO\" secondAttribute=\"leading\" constant=\"20\" id=\"8Cq-2C-1jT\"/>\n                    <constraint firstAttribute=\"trailing\" secondItem=\"Sxx-N6-QgG\" secondAttribute=\"trailing\" constant=\"20\" symbolic=\"YES\" id=\"DxJ-pf-kFf\"/>\n                    <constraint firstAttribute=\"bottom\" secondItem=\"b1p-kF-lsq\" secondAttribute=\"bottom\" constant=\"20\" id=\"Q9y-4K-a5P\"/>\n                    <constraint firstItem=\"oit-Js-Fye\" firstAttribute=\"top\" secondItem=\"Ek0-xw-cVO\" secondAttribute=\"top\" constant=\"20\" id=\"Vbh-h9-kFk\"/>\n                    <constraint firstAttribute=\"trailing\" secondItem=\"gxJ-4P-fMD\" secondAttribute=\"trailing\" constant=\"20\" id=\"bGK-vs-zFN\"/>\n                    <constraint firstItem=\"Sxx-N6-QgG\" firstAttribute=\"top\" secondItem=\"gxJ-4P-fMD\" secondAttribute=\"bottom\" constant=\"20\" id=\"kee-bM-CcC\"/>\n                    <constraint firstItem=\"gxJ-4P-fMD\" firstAttribute=\"leading\" secondItem=\"Ek0-xw-cVO\" secondAttribute=\"leading\" constant=\"20\" id=\"rOV-LN-K3u\"/>\n                    <constraint firstItem=\"gxJ-4P-fMD\" firstAttribute=\"top\" secondItem=\"oit-Js-Fye\" secondAttribute=\"bottom\" constant=\"20\" id=\"yZO-Sz-Rpq\"/>\n                </constraints>\n            </view>\n            <point key=\"canvasLocation\" x=\"-221.5\" y=\"1221.5\"/>\n        </window>\n        <window title=\"Add a Local Source\" allowsToolTipsWhenApplicationIsInactive=\"NO\" autorecalculatesKeyViewLoop=\"NO\" restorable=\"NO\" releasedWhenClosed=\"NO\" visibleAtLaunch=\"NO\" frameAutosaveName=\"\" animationBehavior=\"default\" id=\"Pmx-QU-MSf\">\n            <windowStyleMask key=\"styleMask\" titled=\"YES\" closable=\"YES\"/>\n            <rect key=\"contentRect\" x=\"283\" y=\"305\" width=\"665\" height=\"250\"/>\n            <rect key=\"screenRect\" x=\"0.0\" y=\"0.0\" width=\"2560\" height=\"1415\"/>\n            <view key=\"contentView\" id=\"MCD-5K-sxg\">\n                <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"665\" height=\"250\"/>\n                <autoresizingMask key=\"autoresizingMask\"/>\n                <subviews>\n                    <textField verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"oZ9-Ey-gbW\">\n                        <rect key=\"frame\" x=\"20\" y=\"179\" width=\"625\" height=\"21\"/>\n                        <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                        <textFieldCell key=\"cell\" scrollable=\"YES\" lineBreakMode=\"clipping\" selectable=\"YES\" editable=\"YES\" sendsActionOnEndEditing=\"YES\" borderStyle=\"bezel\" drawsBackground=\"YES\" id=\"78y-xO-Nnp\">\n                            <font key=\"font\" usesAppearanceFont=\"YES\"/>\n                            <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                            <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        </textFieldCell>\n                    </textField>\n                    <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"wER-O8-qwH\">\n                        <rect key=\"frame\" x=\"20\" y=\"214\" width=\"504\" height=\"16\"/>\n                        <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                        <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"Please drag and drop your local directory containing videos, in the textfield below: \" id=\"ExP-Ao-DcG\">\n                            <font key=\"font\" metaFont=\"system\"/>\n                            <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                            <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        </textFieldCell>\n                    </textField>\n                    <imageView horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"4lw-11-KRp\">\n                        <rect key=\"frame\" x=\"22\" y=\"137\" width=\"24\" height=\"24\"/>\n                        <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                        <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" image=\"NSCaution\" id=\"wer-ay-XrD\"/>\n                    </imageView>\n                    <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"m5U-hR-2I7\">\n                        <rect key=\"frame\" x=\"52\" y=\"56\" width=\"595\" height=\"102\"/>\n                        <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                        <textFieldCell key=\"cell\" id=\"wR2-WM-OqJ\">\n                            <font key=\"font\" metaFont=\"system\"/>\n                            <string key=\"title\">On macOS 10.15 and above (Catalina and Big Sur), there are several restrictions to be aware of:\n- Your folder must be on the main disk drive\n- It must be on a non protected user folder (so NOT Downloads, Desktop, Documents)\n\nWe very highly recommend you put your video folders in /Users/shared/ as this is a \"safe\" location to use. </string>\n                            <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                            <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        </textFieldCell>\n                    </textField>\n                    <button verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"zUN-Ew-hU8\">\n                        <rect key=\"frame\" x=\"552\" y=\"14\" width=\"99\" height=\"40\"/>\n                        <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                        <buttonCell key=\"cell\" type=\"push\" title=\"Add Folder\" bezelStyle=\"rounded\" alignment=\"center\" controlSize=\"large\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"Hf6-ae-YCJ\">\n                            <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                            <font key=\"font\" metaFont=\"system\"/>\n                        </buttonCell>\n                        <connections>\n                            <action selector=\"addLocalValidate:\" target=\"-2\" id=\"Mc7-lA-Wlz\"/>\n                        </connections>\n                    </button>\n                    <button verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Lpy-ZW-7Gu\">\n                        <rect key=\"frame\" x=\"470\" y=\"14\" width=\"74\" height=\"40\"/>\n                        <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                        <buttonCell key=\"cell\" type=\"push\" title=\"Cancel\" bezelStyle=\"rounded\" alignment=\"center\" controlSize=\"large\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"1Kd-gi-Gqe\">\n                            <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                            <font key=\"font\" metaFont=\"system\"/>\n                            <string key=\"keyEquivalent\" base64-UTF8=\"YES\">\nGw\n</string>\n                        </buttonCell>\n                        <connections>\n                            <action selector=\"addLocalCancel:\" target=\"-2\" id=\"Mv9-VR-nnl\"/>\n                        </connections>\n                    </button>\n                </subviews>\n            </view>\n            <point key=\"canvasLocation\" x=\"-469.5\" y=\"1565\"/>\n        </window>\n    </objects>\n    <resources>\n        <image name=\"NSCaution\" width=\"32\" height=\"32\"/>\n        <image name=\"NSTouchBarDownloadTemplate\" width=\"20\" height=\"20\"/>\n        <image name=\"antenna.radiowaves.left.and.right\" catalog=\"system\" width=\"16\" height=\"14\"/>\n        <image name=\"book\" catalog=\"system\" width=\"18\" height=\"14\"/>\n        <image name=\"cloud\" catalog=\"system\" width=\"18\" height=\"13\"/>\n        <image name=\"film\" width=\"168\" height=\"132\"/>\n        <image name=\"flame\" width=\"120\" height=\"162\"/>\n        <image name=\"folder\" catalog=\"system\" width=\"18\" height=\"14\"/>\n        <image name=\"helm\" width=\"164\" height=\"201\"/>\n        <image name=\"sparkles\" width=\"133\" height=\"175\"/>\n        <image name=\"tram.fill\" width=\"129\" height=\"221\"/>\n    </resources>\n</document>\n"
  },
  {
    "path": "Resources/MainUI/Settings panels/TimeViewController.swift",
    "content": "//\n//  TimeViewController.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 19/07/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Cocoa\n\nclass TimeViewController: NSViewController {\n    // All the radios\n    @IBOutlet var timeLocationRadio: NSButton!\n    @IBOutlet var timeNightShiftRadio: NSButton!\n    @IBOutlet var timeManualRadio: NSButton!\n    @IBOutlet var timeLightDarkModeRadio: NSButton!\n    @IBOutlet var timeDisabledRadio: NSButton!\n\n    // Night Shift\n    @IBOutlet var nightShiftLabel: NSTextField!\n\n    // Manual\n    @IBOutlet var sunriseTime: NSDatePicker!\n    @IBOutlet var sunsetTime: NSDatePicker!\n\n    // Advanced\n    @IBOutlet var darkModeNightOverride: NSButton!\n\n    @IBOutlet var myLocationImageView: NSImageView!\n\n    @IBOutlet var nightShiftImageView: NSImageView!\n\n    @IBOutlet var manualImageView: NSImageView!\n\n    @IBOutlet var lightModeImageView: NSImageView!\n\n    @IBOutlet var noAdaptImageView: NSImageView!\n    @IBOutlet var popoverCalcMode: NSPopover!\n\n    @IBOutlet var oSunrise: NSTextField!\n    @IBOutlet var eSunrise: NSTextField!\n    @IBOutlet var eSunset: NSTextField!\n    @IBOutlet var oSunset: NSTextField!\n\n    @IBOutlet var timeBarView: NSView!\n\n    @IBOutlet var sunsetWindowPopup: NSPopUpButton!\n\n    lazy var timeFormatter: DateFormatter = {\n        let formatter = DateFormatter()\n        formatter.dateFormat = \"HH:mm\"\n        return formatter\n    }()\n\n    // swiftlint:disable cyclomatic_complexity\n    override func viewDidLoad() {\n        super.viewDidLoad()\n\n        setupDarkMode()\n        DispatchQueue.main.async {\n            self.setupNightShift()\n        }\n\n        if let dateSunrise = timeFormatter.date(from: PrefsTime.manualSunrise) {\n            sunriseTime.dateValue = dateSunrise\n        }\n        if let dateSunset = timeFormatter.date(from: PrefsTime.manualSunset) {\n            sunsetTime.dateValue = dateSunset\n        }\n\n        // Handle the time radios\n        switch PrefsTime.timeMode {\n        case .nightShift:\n            timeNightShiftRadio.state = .on\n        case .manual:\n            timeManualRadio.state = .on\n        case .lightDarkMode:\n            timeLightDarkModeRadio.state = .on\n        case .disabled:\n            timeDisabledRadio.state = .on\n        default:\n            timeLocationRadio.state = .on\n        }\n\n        myLocationImageView.image = Aerial.helper.getSymbol(\"mappin.and.ellipse\")?.tinting(with: .secondaryLabelColor)\n\n        nightShiftImageView.image = Aerial.helper.getSymbol(\"house\")?.tinting(with: .secondaryLabelColor)\n\n        manualImageView.image = Aerial.helper.getSymbol(\"clock\")?.tinting(with: .secondaryLabelColor)\n\n        lightModeImageView.image = Aerial.helper.getSymbol(\"gear\")?.tinting(with: .secondaryLabelColor)\n\n        noAdaptImageView.image = Aerial.helper.getSymbol(\"xmark.circle\")?.tinting(with: .secondaryLabelColor)\n        updateTimeView()\n\n        switch PrefsTime.sunEventWindow {\n        case 60*60:\n            sunsetWindowPopup.selectItem(at: 0)\n        case 60*90:\n            sunsetWindowPopup.selectItem(at: 1)\n        case 60*120:\n            sunsetWindowPopup.selectItem(at: 2)\n        case 60*150:\n            sunsetWindowPopup.selectItem(at: 3)\n        case 60*180:\n            sunsetWindowPopup.selectItem(at: 4)\n        case 60*210:\n            sunsetWindowPopup.selectItem(at: 5)\n        default:\n            sunsetWindowPopup.selectItem(at: 6)\n        }\n    }\n\n    func setupDarkMode() {\n        // Dark Mode is Mojave+\n        if #available(OSX 10.14, *) {\n            if PrefsTime.darkModeNightOverride {\n                darkModeNightOverride.state = .on\n            }\n            // We disable the checkbox if we are on nightShift mode\n            if PrefsTime.timeMode == .lightDarkMode {\n                darkModeNightOverride.isEnabled = false\n            }\n        } else {\n            darkModeNightOverride.isEnabled = false\n        }\n\n        // Light/Dark mode only available on Mojave+\n        let (isLDMCapable, reason: _) = DarkMode.isAvailable()\n        if !isLDMCapable {\n            timeLightDarkModeRadio.isEnabled = false\n        }\n    }\n\n    func setupNightShift() {\n        // Night Shift requires 10.12.4+ and a compatible Mac\n        let (isNSCapable, reason: NSReason) = NightShift.isAvailable()\n        if !isNSCapable {\n            timeNightShiftRadio.isEnabled = false\n        }\n        nightShiftLabel.stringValue = NSReason\n    }\n\n    @IBAction func sunsetSunriseWindowChange(_ sender: NSPopUpButton) {\n        PrefsTime.sunEventWindow = 60 * ((2 + sender.indexOfSelectedItem) * 30)\n\n        updateTimeView()\n    }\n\n    func updateTimeView() {\n        switch PrefsTime.timeMode {\n        case .disabled:\n            timeBarView.isHidden = true\n            return\n        case .lightDarkMode:\n            timeBarView.isHidden = true\n            return\n        case .nightShift:\n            timeBarView.isHidden = false\n        case .manual:\n            timeBarView.isHidden = false\n        case .coordinates:\n            timeBarView.isHidden = true\n            return\n        case .locationService:\n            timeBarView.isHidden = false\n            _ = TimeManagement.sharedInstance.calculateFromCoordinates()\n        }\n\n        let (sunrise, sunset) = TimeManagement.sharedInstance.getSunriseSunset()\n\n        if let lsunrise = sunrise, let lsunset = sunset {\n            let esunrise = lsunrise.addingTimeInterval(TimeInterval(PrefsTime.sunEventWindow))\n            let psunset = lsunset.addingTimeInterval(TimeInterval(-PrefsTime.sunEventWindow))\n\n            oSunrise.stringValue = timeFormatter.string(from: lsunrise)\n            oSunrise.sizeToFit()\n            eSunrise.stringValue = timeFormatter.string(from: esunrise)\n            eSunrise.sizeToFit()\n            eSunset.stringValue = timeFormatter.string(from: psunset)\n            eSunset.sizeToFit()\n            oSunset.stringValue = timeFormatter.string(from: lsunset)\n            oSunset.sizeToFit()\n        }\n    }\n\n    @IBAction func timeModeChange(_ sender: NSButton) {\n        if sender == timeLightDarkModeRadio {\n            darkModeNightOverride.isEnabled = false\n        } else {\n            if #available(OSX 10.14, *) {\n                darkModeNightOverride.isEnabled = true\n            }\n        }\n\n        switch sender {\n        case timeDisabledRadio:\n            PrefsTime.timeMode = .disabled\n        case timeNightShiftRadio:\n            PrefsTime.timeMode = .nightShift\n        case timeManualRadio:\n            PrefsTime.timeMode = .manual\n        case timeLightDarkModeRadio:\n            PrefsTime.timeMode = .lightDarkMode\n        case timeLocationRadio:\n            PrefsTime.timeMode = .locationService\n        default:\n            ()\n        }\n        updateTimeView()\n    }\n\n    @IBAction func sunriseChange(_ sender: NSDatePicker?) {\n        guard let date = sender?.dateValue else { return }\n        PrefsTime.manualSunrise = timeFormatter.string(from: date)\n        updateTimeView()\n    }\n\n    @IBAction func sunsetChange(_ sender: NSDatePicker?) {\n        guard let date = sender?.dateValue else { return }\n        PrefsTime.manualSunset = timeFormatter.string(from: date)\n        updateTimeView()\n    }\n\n    @IBAction func darkModeNightOverrideClick(_ sender: NSButton) {\n        PrefsTime.darkModeNightOverride = sender.state == .on\n    }\n\n    @IBAction func testLocationClick(_ sender: Any) {\n        // Get the location\n        let location = Locations.sharedInstance\n\n        location.getCoordinates(failure: { (_) in\n            // swiftlint:disable:next line_length\n            Aerial.helper.showInfoAlert(title: \"Could not get your location\", text: \"Make sure you enabled location services on your Mac (and Wi-Fi!), and that Aerial (or legacyScreenSaver on macOS 10.15 and later) is allowed to use your location. If you use Aerial Companion, you will also need also allow location services for it.\", button1: \"OK\", caution: true)\n        }, success: { (coordinates) in\n            let lat = String(format: \"%.2f\", coordinates.latitude)\n            let lon = String(format: \"%.2f\", coordinates.longitude)\n\n            Aerial.helper.showInfoAlert(title: \"Success\", text: \"Aerial can access your location (latitude: \\(lat), longitude: \\(lon)) and will use it to show you the correct videos.\")\n\n            self.updateTimeView()\n        })\n    }\n}\n"
  },
  {
    "path": "Resources/MainUI/Settings panels/TimeViewController.xib",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.Cocoa.XIB\" version=\"3.0\" toolsVersion=\"22154\" targetRuntime=\"MacOSX.Cocoa\" propertyAccessControl=\"none\" useAutolayout=\"YES\" customObjectInstantitationMethod=\"direct\">\n    <dependencies>\n        <deployment identifier=\"macosx\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.CocoaPlugin\" version=\"22154\"/>\n        <capability name=\"Image references\" minToolsVersion=\"12.0\"/>\n        <capability name=\"System colors introduced in macOS 10.14\" minToolsVersion=\"10.0\"/>\n        <capability name=\"documents saved in the Xcode 8 format\" minToolsVersion=\"8.0\"/>\n    </dependencies>\n    <objects>\n        <customObject id=\"-2\" userLabel=\"File's Owner\" customClass=\"TimeViewController\" customModule=\"Aerial\" customModuleProvider=\"target\">\n            <connections>\n                <outlet property=\"darkModeNightOverride\" destination=\"1xw-2R-kTW\" id=\"q0x-tC-fcQ\"/>\n                <outlet property=\"eSunrise\" destination=\"0QZ-XQ-Fg5\" id=\"3xt-TS-UQn\"/>\n                <outlet property=\"eSunset\" destination=\"9L4-Ty-HUB\" id=\"me2-pk-OMt\"/>\n                <outlet property=\"lightModeImageView\" destination=\"SzV-m9-ZFE\" id=\"7yC-X9-OdQ\"/>\n                <outlet property=\"manualImageView\" destination=\"6Q8-32-Le7\" id=\"PXh-Xm-JCs\"/>\n                <outlet property=\"myLocationImageView\" destination=\"5Q7-5H-Koj\" id=\"eKk-cq-OiL\"/>\n                <outlet property=\"nightShiftImageView\" destination=\"3kY-Bn-bBw\" id=\"3DH-G6-KrT\"/>\n                <outlet property=\"nightShiftLabel\" destination=\"R2Z-La-EL1\" id=\"uio-Xk-d68\"/>\n                <outlet property=\"noAdaptImageView\" destination=\"SZ1-xU-U63\" id=\"ROX-wG-N0f\"/>\n                <outlet property=\"oSunrise\" destination=\"uVO-CB-CuH\" id=\"8WQ-wE-Fkh\"/>\n                <outlet property=\"oSunset\" destination=\"vXa-af-cok\" id=\"q6a-KH-73v\"/>\n                <outlet property=\"popoverCalcMode\" destination=\"haq-ht-9ck\" id=\"rtx-h8-byw\"/>\n                <outlet property=\"sunriseTime\" destination=\"YLj-jJ-de5\" id=\"4fH-Ra-yJe\"/>\n                <outlet property=\"sunsetTime\" destination=\"7kV-Ca-cPz\" id=\"db8-UR-q9c\"/>\n                <outlet property=\"sunsetWindowPopup\" destination=\"wBa-8A-1ip\" id=\"N3z-z5-UXc\"/>\n                <outlet property=\"timeBarView\" destination=\"vdz-xw-hgB\" id=\"vvG-G8-z7L\"/>\n                <outlet property=\"timeDisabledRadio\" destination=\"jal-bK-WHc\" id=\"mMV-aF-RqH\"/>\n                <outlet property=\"timeLightDarkModeRadio\" destination=\"T3w-0V-R7q\" id=\"Ubv-8y-bZW\"/>\n                <outlet property=\"timeLocationRadio\" destination=\"LqU-wn-EaP\" id=\"gLt-Yg-LP4\"/>\n                <outlet property=\"timeManualRadio\" destination=\"XEl-58-TYp\" id=\"MhF-dh-FDP\"/>\n                <outlet property=\"timeNightShiftRadio\" destination=\"zCA-xo-Kh1\" id=\"OLw-zx-jls\"/>\n                <outlet property=\"view\" destination=\"Hz6-mo-xeY\" id=\"0bl-1N-x8E\"/>\n            </connections>\n        </customObject>\n        <customObject id=\"-1\" userLabel=\"First Responder\" customClass=\"FirstResponder\"/>\n        <customObject id=\"-3\" userLabel=\"Application\" customClass=\"NSObject\"/>\n        <customView translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Hz6-mo-xeY\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"811\" height=\"530\"/>\n            <subviews>\n                <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"XEl-58-TYp\">\n                    <rect key=\"frame\" x=\"97\" y=\"365.5\" width=\"295\" height=\"22\"/>\n                    <buttonCell key=\"cell\" type=\"radio\" title=\"Manually specify sunrise and sunset time\" bezelStyle=\"regularSquare\" imagePosition=\"left\" alignment=\"left\" controlSize=\"large\" inset=\"2\" id=\"IP7-2f-mdT\">\n                        <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"timeModeChange:\" target=\"-2\" id=\"vH1-Sz-mSQ\"/>\n                    </connections>\n                </button>\n                <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"T3w-0V-R7q\">\n                    <rect key=\"frame\" x=\"97\" y=\"324.5\" width=\"545\" height=\"22\"/>\n                    <buttonCell key=\"cell\" type=\"radio\" title=\"Change videos based on Light Mode/Dark Mode (macOS 10.14 Mojave required)\" bezelStyle=\"regularSquare\" imagePosition=\"left\" alignment=\"left\" controlSize=\"large\" inset=\"2\" id=\"grD-eJ-n21\">\n                        <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"timeModeChange:\" target=\"-2\" id=\"0dD-WU-h4D\"/>\n                    </connections>\n                </button>\n                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"fXb-az-Lnm\">\n                    <rect key=\"frame\" x=\"52\" y=\"497\" width=\"228\" height=\"17\"/>\n                    <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"Adapt videos based on time of day\" id=\"4vm-cP-mwk\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"jal-bK-WHc\">\n                    <rect key=\"frame\" x=\"97\" y=\"283.5\" width=\"322\" height=\"22\"/>\n                    <buttonCell key=\"cell\" type=\"radio\" title=\"Do not adapt videos, play anything at random\" bezelStyle=\"regularSquare\" imagePosition=\"left\" alignment=\"left\" controlSize=\"large\" state=\"on\" inset=\"2\" id=\"Qsu-PJ-6Yt\">\n                        <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"timeModeChange:\" target=\"-2\" id=\"342-a6-oKr\"/>\n                    </connections>\n                </button>\n                <imageView horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"SzV-m9-ZFE\">\n                    <rect key=\"frame\" x=\"52\" y=\"324\" width=\"24\" height=\"24\"/>\n                    <constraints>\n                        <constraint firstAttribute=\"width\" constant=\"24\" id=\"ZuI-5i-0Ca\"/>\n                        <constraint firstAttribute=\"height\" constant=\"24\" id=\"pGx-JS-o5B\"/>\n                    </constraints>\n                    <imageCell key=\"cell\" controlSize=\"large\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" image=\"gear\" id=\"h5X-E8-d3J\"/>\n                </imageView>\n                <imageView horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"SZ1-xU-U63\">\n                    <rect key=\"frame\" x=\"52\" y=\"283\" width=\"24\" height=\"24\"/>\n                    <constraints>\n                        <constraint firstAttribute=\"width\" constant=\"24\" id=\"BBi-WG-rkj\"/>\n                        <constraint firstAttribute=\"height\" constant=\"24\" id=\"PwN-td-NBc\"/>\n                    </constraints>\n                    <imageCell key=\"cell\" controlSize=\"large\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" image=\"xmark.circle\" id=\"wdI-Hq-Nfg\"/>\n                </imageView>\n                <imageView horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"6Q8-32-Le7\">\n                    <rect key=\"frame\" x=\"52\" y=\"365\" width=\"24\" height=\"24\"/>\n                    <constraints>\n                        <constraint firstAttribute=\"height\" constant=\"24\" id=\"9zv-VZ-sWn\"/>\n                        <constraint firstAttribute=\"width\" constant=\"24\" id=\"SX0-tc-aLa\"/>\n                    </constraints>\n                    <imageCell key=\"cell\" controlSize=\"large\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" image=\"text.cursor\" id=\"9sa-v9-Pk2\"/>\n                </imageView>\n                <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"LqU-wn-EaP\">\n                    <rect key=\"frame\" x=\"97\" y=\"447.5\" width=\"532\" height=\"22\"/>\n                    <buttonCell key=\"cell\" type=\"radio\" title=\"Use my location (requires location services to be enabled for the screensaver)\" bezelStyle=\"regularSquare\" imagePosition=\"left\" alignment=\"left\" controlSize=\"large\" inset=\"2\" id=\"iCc-tH-zjX\">\n                        <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"timeModeChange:\" target=\"-2\" id=\"fyv-he-5Q5\"/>\n                    </connections>\n                </button>\n                <button toolTip=\"Sunset/sunrise detection requires macOS 10.12.4, a compatible Mac, and location services enabled\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"zCA-xo-Kh1\">\n                    <rect key=\"frame\" x=\"97\" y=\"406.5\" width=\"280\" height=\"22\"/>\n                    <buttonCell key=\"cell\" type=\"radio\" title=\"Use macOS Night Shift for calculations\" bezelStyle=\"regularSquare\" imagePosition=\"left\" alignment=\"left\" controlSize=\"large\" inset=\"2\" id=\"rD2-zV-P26\">\n                        <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"timeModeChange:\" target=\"-2\" id=\"gCt-eg-XWd\"/>\n                    </connections>\n                </button>\n                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"R2Z-La-EL1\">\n                    <rect key=\"frame\" x=\"395\" y=\"409\" width=\"4\" height=\"17\"/>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" id=\"vcy-lb-T6r\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"secondaryLabelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <imageView horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"3kY-Bn-bBw\">\n                    <rect key=\"frame\" x=\"56\" y=\"408\" width=\"20\" height=\"20\"/>\n                    <constraints>\n                        <constraint firstAttribute=\"width\" constant=\"20\" id=\"RQB-Vu-Fep\"/>\n                        <constraint firstAttribute=\"height\" constant=\"20\" id=\"o4Q-8Y-O3E\"/>\n                    </constraints>\n                    <imageCell key=\"cell\" controlSize=\"large\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" image=\"house\" id=\"3SE-5N-cO0\"/>\n                </imageView>\n                <button toolTip=\"This will override the time settings to always show night videos if you have enabled dark mode\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"1xw-2R-kTW\">\n                    <rect key=\"frame\" x=\"197\" y=\"242.5\" width=\"268\" height=\"22\"/>\n                    <buttonCell key=\"cell\" type=\"check\" title=\"Show only night videos in Dark Mode\" bezelStyle=\"regularSquare\" imagePosition=\"left\" controlSize=\"large\" inset=\"2\" id=\"kch-eD-7zN\">\n                        <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"darkModeNightOverrideClick:\" target=\"-2\" id=\"Aa4-FV-gmU\"/>\n                    </connections>\n                </button>\n                <imageView horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"5Q7-5H-Koj\">\n                    <rect key=\"frame\" x=\"56\" y=\"449\" width=\"20\" height=\"20\"/>\n                    <constraints>\n                        <constraint firstAttribute=\"width\" constant=\"20\" id=\"Uh6-lT-zdL\"/>\n                        <constraint firstAttribute=\"height\" constant=\"20\" id=\"pvR-Cn-vNJ\"/>\n                    </constraints>\n                    <imageCell key=\"cell\" controlSize=\"large\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" image=\"mappin.and.ellipse\" id=\"hiP-2o-HMf\"/>\n                </imageView>\n                <box horizontalHuggingPriority=\"20\" verticalHuggingPriority=\"750\" boxType=\"separator\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"rhV-9j-1sD\">\n                    <rect key=\"frame\" x=\"20\" y=\"218\" width=\"771\" height=\"5\"/>\n                </box>\n                <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"jUR-yB-Nrf\">\n                    <rect key=\"frame\" x=\"631\" y=\"437\" width=\"60\" height=\"40\"/>\n                    <buttonCell key=\"cell\" type=\"push\" title=\"Test\" bezelStyle=\"rounded\" alignment=\"center\" controlSize=\"large\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"QMM-O7-3uI\">\n                        <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"testLocationClick:\" target=\"-2\" id=\"sY8-ol-aWu\"/>\n                    </connections>\n                </button>\n                <datePicker verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"YLj-jJ-de5\">\n                    <rect key=\"frame\" x=\"473\" y=\"364\" width=\"44\" height=\"22\"/>\n                    <datePickerCell key=\"cell\" controlSize=\"large\" borderStyle=\"bezel\" alignment=\"left\" id=\"o4w-Dn-pEi\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <date key=\"date\" timeIntervalSinceReferenceDate=\"616854290.413427\">\n                            <!--2020-07-19 12:24:50 +0000-->\n                        </date>\n                        <color key=\"backgroundColor\" name=\"controlBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <datePickerElements key=\"datePickerElements\" hour=\"YES\" minute=\"YES\"/>\n                    </datePickerCell>\n                    <connections>\n                        <action selector=\"sunriseChange:\" target=\"-2\" id=\"zHw-vl-xjH\"/>\n                    </connections>\n                </datePicker>\n                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"l0v-PM-J5T\">\n                    <rect key=\"frame\" x=\"410\" y=\"368\" width=\"57\" height=\"17\"/>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" title=\"Sunrise:\" id=\"6v8-Si-h4y\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"secondaryLabelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <datePicker verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"7kV-Ca-cPz\">\n                    <rect key=\"frame\" x=\"591\" y=\"364\" width=\"44\" height=\"22\"/>\n                    <datePickerCell key=\"cell\" controlSize=\"large\" borderStyle=\"bezel\" alignment=\"left\" id=\"JYg-42-kDw\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <date key=\"date\" timeIntervalSinceReferenceDate=\"616854290.417768\">\n                            <!--2020-07-19 12:24:50 +0000-->\n                        </date>\n                        <color key=\"backgroundColor\" name=\"controlBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <datePickerElements key=\"datePickerElements\" hour=\"YES\" minute=\"YES\"/>\n                    </datePickerCell>\n                    <connections>\n                        <action selector=\"sunsetChange:\" target=\"-2\" id=\"eUB-mi-bd4\"/>\n                    </connections>\n                </datePicker>\n                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"cvF-Ft-Pca\">\n                    <rect key=\"frame\" x=\"532\" y=\"368\" width=\"53\" height=\"17\"/>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" title=\"Sunset:\" id=\"Xij-lB-0vq\">\n                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                        <color key=\"textColor\" name=\"secondaryLabelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <customView translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"vdz-xw-hgB\">\n                    <rect key=\"frame\" x=\"40\" y=\"80\" width=\"732\" height=\"90\"/>\n                    <subviews>\n                        <box boxType=\"custom\" title=\"Box\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Zp0-GE-dK9\">\n                            <rect key=\"frame\" x=\"12\" y=\"67\" width=\"152\" height=\"23\"/>\n                            <view key=\"contentView\" id=\"CpR-FZ-eIH\">\n                                <rect key=\"frame\" x=\"1\" y=\"1\" width=\"150\" height=\"21\"/>\n                                <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                                <subviews>\n                                    <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"nFX-Lz-yGi\">\n                                        <rect key=\"frame\" x=\"58\" y=\"4\" width=\"33\" height=\"14\"/>\n                                        <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"Night\" id=\"JE5-Ja-Nbk\">\n                                            <font key=\"font\" metaFont=\"smallSystem\"/>\n                                            <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                            <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                        </textFieldCell>\n                                    </textField>\n                                </subviews>\n                                <constraints>\n                                    <constraint firstItem=\"nFX-Lz-yGi\" firstAttribute=\"centerY\" secondItem=\"CpR-FZ-eIH\" secondAttribute=\"centerY\" id=\"UYC-Q3-9sO\"/>\n                                    <constraint firstItem=\"nFX-Lz-yGi\" firstAttribute=\"centerX\" secondItem=\"CpR-FZ-eIH\" secondAttribute=\"centerX\" id=\"rIn-LK-flj\"/>\n                                </constraints>\n                            </view>\n                            <constraints>\n                                <constraint firstAttribute=\"width\" constant=\"152\" id=\"ZNw-4n-89g\"/>\n                                <constraint firstAttribute=\"height\" constant=\"23\" id=\"rSe-d7-L9l\"/>\n                            </constraints>\n                            <color key=\"fillColor\" name=\"systemGrayColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        </box>\n                        <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"0QZ-XQ-Fg5\">\n                            <rect key=\"frame\" x=\"262\" y=\"42\" width=\"33\" height=\"16\"/>\n                            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                            <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"8:00\" id=\"Oxc-Xc-OQu\">\n                                <font key=\"font\" usesAppearanceFont=\"YES\"/>\n                                <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                            </textFieldCell>\n                        </textField>\n                        <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"uVO-CB-CuH\">\n                            <rect key=\"frame\" x=\"148\" y=\"42\" width=\"33\" height=\"16\"/>\n                            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                            <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"4:00\" id=\"Eax-qd-GtO\">\n                                <font key=\"font\" usesAppearanceFont=\"YES\"/>\n                                <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                            </textFieldCell>\n                        </textField>\n                        <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"U8K-Gl-kT5\">\n                            <rect key=\"frame\" x=\"-2\" y=\"42\" width=\"33\" height=\"16\"/>\n                            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                            <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"0:00\" id=\"Vjq-KB-B5n\">\n                                <font key=\"font\" usesAppearanceFont=\"YES\"/>\n                                <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                            </textFieldCell>\n                        </textField>\n                        <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"9L4-Ty-HUB\">\n                            <rect key=\"frame\" x=\"454\" y=\"42\" width=\"39\" height=\"16\"/>\n                            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                            <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"19:00\" id=\"aGo-uz-ddR\">\n                                <font key=\"font\" usesAppearanceFont=\"YES\"/>\n                                <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                            </textFieldCell>\n                        </textField>\n                        <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"t0M-Hv-jaA\">\n                            <rect key=\"frame\" x=\"694\" y=\"42\" width=\"40\" height=\"16\"/>\n                            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                            <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"23:59\" id=\"UQd-q5-42m\">\n                                <font key=\"font\" usesAppearanceFont=\"YES\"/>\n                                <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                            </textFieldCell>\n                        </textField>\n                        <box boxType=\"custom\" title=\"Box\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"WEz-ap-rkV\">\n                            <rect key=\"frame\" x=\"468\" y=\"67\" width=\"105\" height=\"23\"/>\n                            <view key=\"contentView\" id=\"dhF-2u-ATO\">\n                                <rect key=\"frame\" x=\"1\" y=\"1\" width=\"103\" height=\"21\"/>\n                                <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                                <subviews>\n                                    <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"GbK-xT-KEy\">\n                                        <rect key=\"frame\" x=\"31\" y=\"4\" width=\"41\" height=\"14\"/>\n                                        <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"Sunset\" id=\"z0f-jl-krE\">\n                                            <font key=\"font\" metaFont=\"smallSystem\"/>\n                                            <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                            <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                        </textFieldCell>\n                                    </textField>\n                                </subviews>\n                                <constraints>\n                                    <constraint firstItem=\"GbK-xT-KEy\" firstAttribute=\"centerX\" secondItem=\"dhF-2u-ATO\" secondAttribute=\"centerX\" id=\"C66-wJ-d2U\"/>\n                                    <constraint firstItem=\"GbK-xT-KEy\" firstAttribute=\"centerY\" secondItem=\"dhF-2u-ATO\" secondAttribute=\"centerY\" id=\"pMA-Jt-c5X\"/>\n                                </constraints>\n                            </view>\n                            <constraints>\n                                <constraint firstAttribute=\"width\" constant=\"105\" id=\"q3z-O5-Wae\"/>\n                                <constraint firstAttribute=\"height\" constant=\"23\" id=\"v55-K1-qVT\"/>\n                            </constraints>\n                            <color key=\"fillColor\" name=\"systemOrangeColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        </box>\n                        <box boxType=\"custom\" title=\"Box\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"jHo-tj-voT\">\n                            <rect key=\"frame\" x=\"276\" y=\"67\" width=\"193\" height=\"23\"/>\n                            <view key=\"contentView\" id=\"ik7-0s-cgZ\">\n                                <rect key=\"frame\" x=\"1\" y=\"1\" width=\"191\" height=\"21\"/>\n                                <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                                <subviews>\n                                    <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"0Qq-cT-bxq\">\n                                        <rect key=\"frame\" x=\"83\" y=\"4\" width=\"25\" height=\"14\"/>\n                                        <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"Day\" id=\"zCr-fA-fYP\">\n                                            <font key=\"font\" metaFont=\"smallSystem\"/>\n                                            <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                            <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                        </textFieldCell>\n                                    </textField>\n                                </subviews>\n                                <constraints>\n                                    <constraint firstItem=\"0Qq-cT-bxq\" firstAttribute=\"centerX\" secondItem=\"ik7-0s-cgZ\" secondAttribute=\"centerX\" id=\"MNh-YG-kbc\"/>\n                                    <constraint firstItem=\"0Qq-cT-bxq\" firstAttribute=\"centerY\" secondItem=\"ik7-0s-cgZ\" secondAttribute=\"centerY\" id=\"VjW-EH-h2V\"/>\n                                </constraints>\n                            </view>\n                            <constraints>\n                                <constraint firstAttribute=\"height\" constant=\"23\" id=\"H5s-Db-nDn\"/>\n                                <constraint firstAttribute=\"width\" constant=\"193\" id=\"t2b-DK-989\"/>\n                            </constraints>\n                            <color key=\"fillColor\" name=\"systemTealColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        </box>\n                        <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"vXa-af-cok\">\n                            <rect key=\"frame\" x=\"554\" y=\"42\" width=\"40\" height=\"16\"/>\n                            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                            <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"22:00\" id=\"K4c-mR-rIM\">\n                                <font key=\"font\" usesAppearanceFont=\"YES\"/>\n                                <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                            </textFieldCell>\n                        </textField>\n                        <box boxType=\"custom\" title=\"Box\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"86O-t6-EDO\">\n                            <rect key=\"frame\" x=\"572\" y=\"67\" width=\"144\" height=\"23\"/>\n                            <view key=\"contentView\" id=\"yIe-n9-Oaw\">\n                                <rect key=\"frame\" x=\"1\" y=\"1\" width=\"142\" height=\"21\"/>\n                                <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                                <subviews>\n                                    <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"0L0-hY-N6Q\">\n                                        <rect key=\"frame\" x=\"54\" y=\"4\" width=\"33\" height=\"14\"/>\n                                        <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"Night\" id=\"QgN-m9-IBW\">\n                                            <font key=\"font\" metaFont=\"smallSystem\"/>\n                                            <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                            <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                        </textFieldCell>\n                                    </textField>\n                                </subviews>\n                                <constraints>\n                                    <constraint firstItem=\"0L0-hY-N6Q\" firstAttribute=\"centerX\" secondItem=\"yIe-n9-Oaw\" secondAttribute=\"centerX\" id=\"Btu-Q8-TdS\"/>\n                                    <constraint firstItem=\"0L0-hY-N6Q\" firstAttribute=\"centerY\" secondItem=\"yIe-n9-Oaw\" secondAttribute=\"centerY\" id=\"Vzf-ZP-iiR\"/>\n                                </constraints>\n                            </view>\n                            <constraints>\n                                <constraint firstAttribute=\"width\" constant=\"144\" id=\"5ok-Ua-szH\"/>\n                                <constraint firstAttribute=\"height\" constant=\"23\" id=\"sAP-sX-a85\"/>\n                            </constraints>\n                            <color key=\"fillColor\" name=\"systemGrayColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        </box>\n                        <box boxType=\"custom\" title=\"Box\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"cYJ-Ds-231\">\n                            <rect key=\"frame\" x=\"163\" y=\"67\" width=\"114\" height=\"23\"/>\n                            <view key=\"contentView\" id=\"rhA-UR-hh1\">\n                                <rect key=\"frame\" x=\"1\" y=\"1\" width=\"112\" height=\"21\"/>\n                                <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                                <subviews>\n                                    <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"iWB-9n-bIq\">\n                                        <rect key=\"frame\" x=\"34\" y=\"4\" width=\"44\" height=\"14\"/>\n                                        <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"Sunrise\" id=\"Ubc-c5-jGG\">\n                                            <font key=\"font\" metaFont=\"smallSystem\"/>\n                                            <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                            <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                        </textFieldCell>\n                                    </textField>\n                                </subviews>\n                                <constraints>\n                                    <constraint firstItem=\"iWB-9n-bIq\" firstAttribute=\"centerX\" secondItem=\"rhA-UR-hh1\" secondAttribute=\"centerX\" id=\"AqW-Vk-zEz\"/>\n                                    <constraint firstItem=\"iWB-9n-bIq\" firstAttribute=\"centerY\" secondItem=\"rhA-UR-hh1\" secondAttribute=\"centerY\" id=\"Vnd-1x-1So\"/>\n                                </constraints>\n                            </view>\n                            <constraints>\n                                <constraint firstAttribute=\"height\" constant=\"23\" id=\"2U7-wR-1a7\"/>\n                                <constraint firstAttribute=\"width\" constant=\"114\" id=\"7pA-Ax-4BU\"/>\n                            </constraints>\n                            <color key=\"fillColor\" name=\"systemPurpleColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        </box>\n                        <popUpButton verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"wBa-8A-1ip\">\n                            <rect key=\"frame\" x=\"176\" y=\"0.0\" width=\"81\" height=\"40\"/>\n                            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                            <popUpButtonCell key=\"cell\" type=\"push\" title=\"1h00\" bezelStyle=\"rounded\" alignment=\"left\" controlSize=\"large\" lineBreakMode=\"truncatingTail\" state=\"on\" borderStyle=\"borderAndBezel\" imageScaling=\"proportionallyDown\" inset=\"2\" selectedItem=\"amd-in-7o2\" id=\"Git-gJ-WAB\">\n                                <behavior key=\"behavior\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                                <font key=\"font\" size=\"14\" name=\"HelveticaNeue\"/>\n                                <menu key=\"menu\" id=\"HRT-dm-LqQ\">\n                                    <items>\n                                        <menuItem title=\"1h00\" state=\"on\" id=\"amd-in-7o2\"/>\n                                        <menuItem title=\"1h30\" id=\"aQL-fk-KD5\"/>\n                                        <menuItem title=\"2h00\" id=\"Fzw-U1-fP7\"/>\n                                        <menuItem title=\"2h30\" id=\"eDW-2m-q3I\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                        </menuItem>\n                                        <menuItem title=\"3h00\" id=\"UEm-Qb-uPk\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                        </menuItem>\n                                        <menuItem title=\"3h30\" id=\"TNr-br-72p\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                        </menuItem>\n                                        <menuItem title=\"4h00\" id=\"2sq-Af-aPT\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                        </menuItem>\n                                    </items>\n                                </menu>\n                            </popUpButtonCell>\n                            <connections>\n                                <action selector=\"sunsetSunriseWindowChange:\" target=\"-2\" id=\"mOQ-LO-BK6\"/>\n                            </connections>\n                        </popUpButton>\n                        <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"XcG-RN-UwO\">\n                            <rect key=\"frame\" x=\"8\" y=\"12\" width=\"159\" height=\"17\"/>\n                            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                            <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" alignment=\"right\" title=\"Sunset/Sunrise window:\" id=\"EwB-Mo-5qO\">\n                                <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                            </textFieldCell>\n                        </textField>\n                    </subviews>\n                    <constraints>\n                        <constraint firstItem=\"jHo-tj-voT\" firstAttribute=\"leading\" secondItem=\"cYJ-Ds-231\" secondAttribute=\"trailing\" constant=\"-1\" id=\"1Kg-JI-moE\"/>\n                        <constraint firstItem=\"86O-t6-EDO\" firstAttribute=\"centerY\" secondItem=\"cYJ-Ds-231\" secondAttribute=\"centerY\" id=\"5Mn-3h-rgU\"/>\n                        <constraint firstItem=\"86O-t6-EDO\" firstAttribute=\"leading\" secondItem=\"WEz-ap-rkV\" secondAttribute=\"trailing\" constant=\"-1\" id=\"7FC-kh-i8a\"/>\n                        <constraint firstItem=\"cYJ-Ds-231\" firstAttribute=\"leading\" secondItem=\"Zp0-GE-dK9\" secondAttribute=\"trailing\" constant=\"-1\" id=\"IYR-nr-TfM\"/>\n                        <constraint firstItem=\"WEz-ap-rkV\" firstAttribute=\"centerY\" secondItem=\"cYJ-Ds-231\" secondAttribute=\"centerY\" id=\"N4J-IQ-sW0\"/>\n                        <constraint firstItem=\"cYJ-Ds-231\" firstAttribute=\"centerY\" secondItem=\"Zp0-GE-dK9\" secondAttribute=\"centerY\" id=\"P6T-tt-cWP\"/>\n                        <constraint firstItem=\"jHo-tj-voT\" firstAttribute=\"centerY\" secondItem=\"cYJ-Ds-231\" secondAttribute=\"centerY\" id=\"UXn-V8-Pwb\"/>\n                        <constraint firstAttribute=\"height\" constant=\"90\" id=\"VHm-sF-PXZ\"/>\n                        <constraint firstItem=\"Zp0-GE-dK9\" firstAttribute=\"leading\" secondItem=\"vdz-xw-hgB\" secondAttribute=\"leading\" constant=\"12\" id=\"Yc4-t2-NdY\"/>\n                        <constraint firstAttribute=\"width\" constant=\"732\" id=\"cup-4N-4h1\"/>\n                        <constraint firstItem=\"WEz-ap-rkV\" firstAttribute=\"leading\" secondItem=\"jHo-tj-voT\" secondAttribute=\"trailing\" constant=\"-1\" id=\"ghd-BK-aQO\"/>\n                        <constraint firstItem=\"Zp0-GE-dK9\" firstAttribute=\"top\" secondItem=\"vdz-xw-hgB\" secondAttribute=\"top\" id=\"rrE-Ha-Su0\"/>\n                    </constraints>\n                </customView>\n                <imageView horizontalHuggingPriority=\"25\" verticalHuggingPriority=\"25\" horizontalCompressionResistancePriority=\"75\" verticalCompressionResistancePriority=\"75\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"bBG-vS-GGt\">\n                    <rect key=\"frame\" x=\"16\" y=\"481\" width=\"28\" height=\"45\"/>\n                    <constraints>\n                        <constraint firstAttribute=\"height\" constant=\"34\" id=\"1cK-Xg-IhY\"/>\n                        <constraint firstAttribute=\"width\" constant=\"28\" id=\"Z2r-jQ-g3Y\"/>\n                    </constraints>\n                    <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyUpOrDown\" id=\"StZ-e0-WcA\">\n                        <imageReference key=\"image\" image=\"clock\" catalog=\"system\" symbolScale=\"large\"/>\n                    </imageCell>\n                    <color key=\"contentTintColor\" name=\"controlAccentColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                </imageView>\n            </subviews>\n            <constraints>\n                <constraint firstItem=\"T3w-0V-R7q\" firstAttribute=\"centerY\" secondItem=\"SzV-m9-ZFE\" secondAttribute=\"centerY\" id=\"1C6-p4-PbP\"/>\n                <constraint firstItem=\"YLj-jJ-de5\" firstAttribute=\"firstBaseline\" secondItem=\"XEl-58-TYp\" secondAttribute=\"firstBaseline\" id=\"29z-SS-dMk\"/>\n                <constraint firstItem=\"jal-bK-WHc\" firstAttribute=\"leading\" secondItem=\"SZ1-xU-U63\" secondAttribute=\"trailing\" constant=\"24\" id=\"3kv-J0-tRG\"/>\n                <constraint firstItem=\"l0v-PM-J5T\" firstAttribute=\"leading\" secondItem=\"XEl-58-TYp\" secondAttribute=\"trailing\" constant=\"20\" id=\"7Xe-Gv-id2\"/>\n                <constraint firstItem=\"zCA-xo-Kh1\" firstAttribute=\"leading\" secondItem=\"LqU-wn-EaP\" secondAttribute=\"leading\" id=\"AMm-2n-jdh\"/>\n                <constraint firstItem=\"LqU-wn-EaP\" firstAttribute=\"leading\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"leading\" constant=\"100\" id=\"CUP-VN-gIS\"/>\n                <constraint firstItem=\"bBG-vS-GGt\" firstAttribute=\"top\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"top\" constant=\"10\" id=\"Cqv-FR-TQh\"/>\n                <constraint firstItem=\"vdz-xw-hgB\" firstAttribute=\"top\" secondItem=\"rhV-9j-1sD\" secondAttribute=\"bottom\" constant=\"50\" id=\"DbC-Ao-aSf\"/>\n                <constraint firstItem=\"T3w-0V-R7q\" firstAttribute=\"leading\" secondItem=\"SzV-m9-ZFE\" secondAttribute=\"trailing\" constant=\"24\" id=\"E3o-tm-DiB\"/>\n                <constraint firstItem=\"LqU-wn-EaP\" firstAttribute=\"centerY\" secondItem=\"5Q7-5H-Koj\" secondAttribute=\"centerY\" id=\"EKf-dc-uzH\"/>\n                <constraint firstItem=\"jUR-yB-Nrf\" firstAttribute=\"firstBaseline\" secondItem=\"LqU-wn-EaP\" secondAttribute=\"firstBaseline\" id=\"G7i-MT-1b6\"/>\n                <constraint firstAttribute=\"width\" relation=\"greaterThanOrEqual\" constant=\"811\" id=\"Gyk-hr-C9a\"/>\n                <constraint firstItem=\"1xw-2R-kTW\" firstAttribute=\"top\" secondItem=\"jal-bK-WHc\" secondAttribute=\"bottom\" constant=\"24\" id=\"HOQ-s7-PQo\"/>\n                <constraint firstItem=\"rhV-9j-1sD\" firstAttribute=\"top\" secondItem=\"1xw-2R-kTW\" secondAttribute=\"bottom\" constant=\"24\" id=\"Is8-P5-jAv\"/>\n                <constraint firstItem=\"XEl-58-TYp\" firstAttribute=\"leading\" secondItem=\"LqU-wn-EaP\" secondAttribute=\"leading\" id=\"Mj4-ED-9dl\"/>\n                <constraint firstItem=\"YLj-jJ-de5\" firstAttribute=\"leading\" secondItem=\"l0v-PM-J5T\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"OZk-ZB-CPQ\"/>\n                <constraint firstItem=\"T3w-0V-R7q\" firstAttribute=\"leading\" secondItem=\"LqU-wn-EaP\" secondAttribute=\"leading\" id=\"PeE-G6-1f5\"/>\n                <constraint firstItem=\"cvF-Ft-Pca\" firstAttribute=\"leading\" secondItem=\"YLj-jJ-de5\" secondAttribute=\"trailing\" constant=\"20\" id=\"Rez-W6-Vbi\"/>\n                <constraint firstItem=\"bBG-vS-GGt\" firstAttribute=\"leading\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"leading\" constant=\"16\" id=\"Rlu-UD-UtY\"/>\n                <constraint firstItem=\"LqU-wn-EaP\" firstAttribute=\"leading\" secondItem=\"5Q7-5H-Koj\" secondAttribute=\"trailing\" constant=\"24\" id=\"TEL-2p-XDa\"/>\n                <constraint firstItem=\"R2Z-La-EL1\" firstAttribute=\"leading\" secondItem=\"zCA-xo-Kh1\" secondAttribute=\"trailing\" constant=\"20\" id=\"UiX-kK-HcY\"/>\n                <constraint firstItem=\"XEl-58-TYp\" firstAttribute=\"top\" secondItem=\"zCA-xo-Kh1\" secondAttribute=\"bottom\" constant=\"24\" id=\"ZEG-tE-BAB\"/>\n                <constraint firstItem=\"XEl-58-TYp\" firstAttribute=\"leading\" secondItem=\"6Q8-32-Le7\" secondAttribute=\"trailing\" constant=\"24\" id=\"ZEi-CJ-nj9\"/>\n                <constraint firstItem=\"XEl-58-TYp\" firstAttribute=\"centerY\" secondItem=\"6Q8-32-Le7\" secondAttribute=\"centerY\" id=\"Zc1-5z-xn7\"/>\n                <constraint firstItem=\"jal-bK-WHc\" firstAttribute=\"leading\" secondItem=\"LqU-wn-EaP\" secondAttribute=\"leading\" id=\"a2c-7w-LYJ\"/>\n                <constraint firstItem=\"7kV-Ca-cPz\" firstAttribute=\"leading\" secondItem=\"cvF-Ft-Pca\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"aJN-5y-9S8\"/>\n                <constraint firstItem=\"LqU-wn-EaP\" firstAttribute=\"top\" secondItem=\"fXb-az-Lnm\" secondAttribute=\"bottom\" constant=\"30\" id=\"afX-yP-bqK\"/>\n                <constraint firstItem=\"zCA-xo-Kh1\" firstAttribute=\"centerY\" secondItem=\"3kY-Bn-bBw\" secondAttribute=\"centerY\" id=\"am2-S8-ysl\"/>\n                <constraint firstItem=\"R2Z-La-EL1\" firstAttribute=\"firstBaseline\" secondItem=\"zCA-xo-Kh1\" secondAttribute=\"firstBaseline\" id=\"biz-ik-YhJ\"/>\n                <constraint firstItem=\"T3w-0V-R7q\" firstAttribute=\"top\" secondItem=\"YLj-jJ-de5\" secondAttribute=\"bottom\" constant=\"20\" id=\"d7s-Eo-Jc6\"/>\n                <constraint firstItem=\"zCA-xo-Kh1\" firstAttribute=\"leading\" secondItem=\"3kY-Bn-bBw\" secondAttribute=\"trailing\" constant=\"24\" id=\"dS4-6a-TcH\"/>\n                <constraint firstItem=\"zCA-xo-Kh1\" firstAttribute=\"top\" secondItem=\"LqU-wn-EaP\" secondAttribute=\"bottom\" constant=\"24\" id=\"e0E-7q-0vG\"/>\n                <constraint firstItem=\"fXb-az-Lnm\" firstAttribute=\"top\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"top\" constant=\"16\" id=\"e1J-af-CbM\"/>\n                <constraint firstItem=\"cvF-Ft-Pca\" firstAttribute=\"firstBaseline\" secondItem=\"XEl-58-TYp\" secondAttribute=\"firstBaseline\" id=\"fAq-tn-aMU\"/>\n                <constraint firstAttribute=\"trailing\" secondItem=\"rhV-9j-1sD\" secondAttribute=\"trailing\" constant=\"20\" id=\"fw1-oT-QgB\"/>\n                <constraint firstItem=\"vdz-xw-hgB\" firstAttribute=\"centerX\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"centerX\" id=\"h4u-EA-tX2\"/>\n                <constraint firstItem=\"1xw-2R-kTW\" firstAttribute=\"leading\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"leading\" constant=\"200\" id=\"iWo-qu-RrJ\"/>\n                <constraint firstItem=\"jUR-yB-Nrf\" firstAttribute=\"leading\" secondItem=\"LqU-wn-EaP\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"jMh-0B-OIF\"/>\n                <constraint firstItem=\"7kV-Ca-cPz\" firstAttribute=\"firstBaseline\" secondItem=\"XEl-58-TYp\" secondAttribute=\"firstBaseline\" id=\"mRv-4q-kfe\"/>\n                <constraint firstAttribute=\"height\" relation=\"greaterThanOrEqual\" constant=\"530\" id=\"q7w-zU-h0W\"/>\n                <constraint firstItem=\"rhV-9j-1sD\" firstAttribute=\"leading\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"leading\" constant=\"20\" id=\"rDD-bc-Q8Q\"/>\n                <constraint firstItem=\"fXb-az-Lnm\" firstAttribute=\"leading\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"leading\" constant=\"54\" id=\"sNR-1K-TIJ\"/>\n                <constraint firstItem=\"jal-bK-WHc\" firstAttribute=\"centerY\" secondItem=\"SZ1-xU-U63\" secondAttribute=\"centerY\" id=\"soO-h3-yu5\"/>\n                <constraint firstItem=\"l0v-PM-J5T\" firstAttribute=\"firstBaseline\" secondItem=\"XEl-58-TYp\" secondAttribute=\"firstBaseline\" id=\"str-Gx-yrV\"/>\n                <constraint firstItem=\"jal-bK-WHc\" firstAttribute=\"top\" secondItem=\"T3w-0V-R7q\" secondAttribute=\"bottom\" constant=\"24\" id=\"yOP-JQ-Rku\"/>\n            </constraints>\n            <point key=\"canvasLocation\" x=\"-90\" y=\"258\"/>\n        </customView>\n        <viewController id=\"T2g-tH-hja\" userLabel=\"Popover View Controller\">\n            <connections>\n                <outlet property=\"view\" destination=\"80v-lr-J8L\" id=\"h2m-Be-U48\"/>\n            </connections>\n        </viewController>\n        <popover behavior=\"t\" id=\"haq-ht-9ck\">\n            <connections>\n                <outlet property=\"contentViewController\" destination=\"T2g-tH-hja\" id=\"moa-Ap-KMU\"/>\n            </connections>\n        </popover>\n        <customView id=\"80v-lr-J8L\" userLabel=\"Time calculation popover\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"374\" height=\"457\"/>\n            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n            <subviews>\n                <textField focusRingType=\"none\" verticalHuggingPriority=\"750\" horizontalCompressionResistancePriority=\"250\" fixedFrame=\"YES\" preferredMaxLayoutWidth=\"334\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"jyx-HG-COw\">\n                    <rect key=\"frame\" x=\"18\" y=\"50\" width=\"338\" height=\"259\"/>\n                    <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                    <textFieldCell key=\"cell\" selectable=\"YES\" refusesFirstResponder=\"YES\" id=\"Vgk-5b-0X9\">\n                        <font key=\"font\" metaFont=\"message\" size=\"11\"/>\n                        <string key=\"title\">There are two ways to calculate the sunset and sunrise time:\n\n- Strict (0°): Calculate when the center of the Sun crosses the horizon\n\n- Official (0.83°): Calculate when the Sun completely crosses the horizon\n\nOr instead of sunrise and sunset, you can pick from three options for the time of dawn and dusk:\n\n- Civil (6°): Calculate when the natural sunlight stops/starts requiring artificial light compensation\n\n- Nautical (12°): Calculate when stars stop/start being seen\n\n- Astronomical (18°): Calculate the point when the sun no longer interferes with astronomical observations</string>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <textField focusRingType=\"none\" verticalHuggingPriority=\"750\" horizontalCompressionResistancePriority=\"250\" fixedFrame=\"YES\" preferredMaxLayoutWidth=\"334\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"T3E-mU-IQr\">\n                    <rect key=\"frame\" x=\"18\" y=\"339\" width=\"338\" height=\"98\"/>\n                    <autoresizingMask key=\"autoresizingMask\" flexibleMinY=\"YES\"/>\n                    <textFieldCell key=\"cell\" selectable=\"YES\" refusesFirstResponder=\"YES\" id=\"9lO-Zu-OSD\">\n                        <font key=\"font\" metaFont=\"message\" size=\"11\"/>\n                        <string key=\"title\">Coordinates are expressed in degrees, e.g.:\n- Latitude : 48.85837\n- Longitude : 2.294483\n\nYou can either enter those manually or try to use Location Services on your Mac by clicking the icon next to the longitude button. You may be asked for permission.</string>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <button verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"CPC-0g-CgG\">\n                    <rect key=\"frame\" x=\"20\" y=\"20\" width=\"334\" height=\"25\"/>\n                    <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMaxY=\"YES\"/>\n                    <buttonCell key=\"cell\" type=\"bevel\" title=\"You can find more information on Wikipedia\" bezelStyle=\"rounded\" alignment=\"center\" refusesFirstResponder=\"YES\" inset=\"2\" id=\"LBg-ct-tm3\">\n                        <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" metaFont=\"message\" size=\"11\"/>\n                    </buttonCell>\n                </button>\n            </subviews>\n            <point key=\"canvasLocation\" x=\"1243\" y=\"28\"/>\n        </customView>\n    </objects>\n    <resources>\n        <image name=\"clock\" catalog=\"system\" width=\"20\" height=\"20\"/>\n        <image name=\"gear\" width=\"153\" height=\"177\"/>\n        <image name=\"house\" width=\"161\" height=\"153\"/>\n        <image name=\"mappin.and.ellipse\" width=\"133\" height=\"173\"/>\n        <image name=\"text.cursor\" width=\"145\" height=\"159\"/>\n        <image name=\"xmark.circle\" width=\"141\" height=\"155\"/>\n    </resources>\n</document>\n"
  },
  {
    "path": "Resources/MainUI/SidebarViewController.swift",
    "content": "//\n//  SidebarViewController.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 15/07/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Cocoa\n\nenum SidebarMenus {\n    case modern, videos, settings, infos\n}\n\nclass SidebarViewController: NSViewController {\n\n    @IBOutlet var sidebarOutlineView: SidebarOutlineView!\n\n    // For the download indicator\n    @IBOutlet var downloadIndicator: NSVisualEffectView!\n    @IBOutlet var downloadIndicatorProgress: NSProgressIndicator!\n    @IBOutlet var downloadIndicatorLabel: NSTextField!\n    @IBOutlet var downloadCancelButton: NSButton!\n\n    var windowController: PanelWindowController?\n\n    // Always start with the videos panel selected\n    var menuSelection: SidebarMenus = .modern\n\n    @IBOutlet var closeButton: NSButton!\n\n    var menuPath = \"\"   // eh...\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n\n        if #available(OSX 10.16, *) {\n            closeButton.isHighlighted = true\n        } else {\n            // For some reason we need this on 10.12/10.13, there's a bug that somehow inverts colors in the recent Big Sur SDK for those older OSes\n            sidebarOutlineView.backgroundColor = .clear\n            sidebarOutlineView.gridColor = .alternateSelectedControlColor\n        }\n\n        sidebarOutlineView.delegate = self\n        sidebarOutlineView.dataSource = self\n\n        // Setup the updates for the download status\n        let videoManager = VideoManager.sharedInstance\n        videoManager.addCallback { done, total in\n            self.updateDownloads(done: done, total: total, progress: 0)\n        }\n        videoManager.addProgressCallback { done, total, progress in\n            self.updateDownloads(done: done, total: total, progress: progress)\n        }\n\n        downloadIndicator.isHidden = true\n        downloadIndicatorProgress.doubleValue = 0\n    }\n\n    override func viewDidAppear() {\n        self.reloadSidebar()\n    }\n\n    private func updateSidebarMenu(_ menu: SidebarMenus) {\n        if menu != menuSelection {\n            windowController?.switchFrom(menuSelection, to: menu)\n\n            // Make sure we mark the current one\n            menuSelection = menu\n\n            sidebarOutlineView.reloadData()\n            sidebarOutlineView.expandItem(nil, expandChildren: true)\n            sidebarOutlineView.selectRowIndexes([1], byExtendingSelection: false)\n        }\n    }\n\n    @IBAction func closeButton(_ sender: Any) {\n        windowController!.stopVideo()\n\n        if !downloadIndicator.isHidden {\n            // swiftlint:disable:next line_length\n            if !Aerial.helper.showAlert(question: \"Downloads still in progress\", text: \"Your video downloads are still in progress. Are you sure you want to quit ? This will abandon your current downloads.\", button1: \"Quit and Abandon Downloads\", button2: \"Cancel\") {\n                return\n            }\n        }\n\n        if Aerial.helper.appMode {\n            NSApplication.shared.terminate(nil)\n        } else {\n            if Aerial.helper.underCompanion {\n                windowController!.window?.close()\n            } else {\n                windowController!.window?.sheetParent?.endSheet(windowController!.window!)\n            }\n        }\n    }\n\n    // MARK: Download indicator\n    // Update the status of the download bar at the bottom of the sidebar\n    func updateDownloads(done: Int, total: Int, progress: Double) {\n        if total == 0 {\n            downloadIndicator.isHidden = true\n            downloadIndicatorProgress.doubleValue = 0\n\n            windowController!.updateViewInPlace()\n            // Sidebar.instance.refreshVideos()\n            /*\n            sidebarOutlineView.reloadData()\n            sidebarOutlineView.expandItem(nil, expandChildren: true)\n            sidebarOutlineView.selectRowIndexes([1], byExtendingSelection: false)\n            */\n        } else if progress == 0 {\n            downloadIndicator.isHidden = false\n            downloadIndicatorProgress.doubleValue = Double(done)\n            downloadIndicatorProgress.maxValue = Double(total)\n            downloadIndicatorProgress.toolTip = \"Downloading \\(done) / \\(total)\"\n            downloadIndicatorLabel.stringValue = \"Downloading \\(done) / \\(total)\"\n        } else {\n            downloadIndicator.isHidden = false\n            downloadIndicatorProgress.doubleValue = Double(done) + progress\n        }\n    }\n\n    @IBAction func cancelDownloads(_ sender: Any) {\n        let videoManager = VideoManager.sharedInstance\n        videoManager.cancelAll()\n    }\n}\n\nextension SidebarViewController: NSOutlineViewDataSource {\n\n    func outlineView(_ outlineView: NSOutlineView, numberOfChildrenOfItem item: Any?) -> Int {\n        if let header = item as? Sidebar.Header {\n            return header.entries.count\n        }\n        debugLog(\"child count \\(Sidebar.instance.modern.count)\")\n        return Sidebar.instance.modern.count\n    }\n\n    func outlineView(_ outlineView: NSOutlineView, child index: Int, ofItem item: Any?) -> Any {\n        if let header = item as? Sidebar.Header {\n            return header.entries[index]\n        }\n\n        return Sidebar.instance.modern[index]\n    }\n\n    func outlineView(_ outlineView: NSOutlineView, isItemExpandable item: Any) -> Bool {\n        if item is Sidebar.Header {\n            return true\n        }\n\n        return false\n    }\n\n    func outlineView(_ outlineView: NSOutlineView, heightOfRowByItem item: Any) -> CGFloat {\n        if item is Sidebar.Header {\n            return 24\n        } else {\n            return 30\n        }\n    }\n    \n    func reloadSidebar() {\n        // We need to reload our sidebar\n        // Sidebar.instance.refreshVideos()\n        debugLog(\"reload sidebar\")\n        let set = sidebarOutlineView.selectedRowIndexes\n\n        sidebarOutlineView.reloadData()\n        sidebarOutlineView.expandItem(nil, expandChildren: true)\n\n        if set.isEmpty {\n            debugLog(\"empty set\")\n            sidebarOutlineView.selectRowIndexes([1], byExtendingSelection: false)\n        } else {\n            debugLog(\"re set ing\")\n            sidebarOutlineView.selectRowIndexes(set, byExtendingSelection: false)\n\n        }\n    }\n}\n\nextension SidebarViewController: NSOutlineViewDelegate {\n\n    func outlineView(_ outlineView: NSOutlineView, viewFor tableColumn: NSTableColumn?, item: Any) -> NSView? {\n        var view: NSTableCellView?\n\n        if let header = item as? Sidebar.Header {\n            view = outlineView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: \"HeaderCell\"), owner: self) as? NSTableCellView\n            if let textField = view?.textField {\n                textField.stringValue = header.name\n            }\n        } else if let entry = item as? Sidebar.MenuEntry {\n            view = outlineView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: \"DataCell\"), owner: self) as? NSTableCellView\n            if let textField = view?.textField {\n                textField.stringValue = entry.name\n            }\n            if let imageView = view?.imageView {\n                imageView.image = Sidebar.iconFor(entry.path, name: entry.name)\n                imageView.image?.isTemplate = true\n                imageView.sizeThatFits(CGSize(width: 24, height: 24))   // Hmm\n            }\n        }\n\n        // More code here\n        return view\n    }\n\n    func outlineView(_ outlineView: NSOutlineView, shouldSelectItem item: Any) -> Bool {\n        if item is Sidebar.Header {\n            return false\n        }\n\n        return true\n    }\n    func outlineViewSelectionDidChange(_ notification: Notification) {\n        guard let outlineView = notification.object as? NSOutlineView else {\n            return\n        }\n\n        let selectedIndex = outlineView.selectedRow\n        if let entry = outlineView.item(atRow: selectedIndex) as? Sidebar.MenuEntry {\n            windowController!.switchTo(entry.path)\n        }\n    }\n\n    func outlineView(_ outlineView: NSOutlineView, shouldShowOutlineCellForItem item: Any) -> Bool {\n        return false\n    }\n\n    @available(OSX 10.16, *)\n    func outlineView(_ outlineView: NSOutlineView, tintConfigurationForItem item: Any) -> NSTintConfiguration? {\n        if let entry = item as? Sidebar.MenuEntry {\n            if entry.name == \"Favorites\" {\n                return NSTintConfiguration(fixedColor: .init(red: 0.996, green: 0.741, blue: 0.066, alpha: 1.0))\n            } else {\n                return NSTintConfiguration.default\n            }\n        }\n\n        return nil\n    }\n\n}\n\n// Right click menu\n/*extension SidebarViewController: SidebarOutlineViewDelegate {\n    // swiftlint:disable cyclomatic_complexity\n    func outlineView(outlineView: NSOutlineView, menuForItem item: Any) -> NSMenu? {\n        // Make sure we're right clicking a menu entry\n        if let entry = item as? Sidebar.MenuEntry {\n            if entry.path.starts(with: \"videos:\") {\n                let idx = entry.path.firstIndex(of: \":\")\n                let path = String(entry.path[idx!...].dropFirst()) // Oh Swift...\n\n                menuPath = path         // Store it for later use in selectors, it's ugly I know\n\n                // Grab all the videos\n                var videos: [AerialVideo]\n\n                if let mode = VideoList.instance.modeFromPath(path) {\n                    let index = Int(path.split(separator: \":\")[1])!\n                    videos = VideoList.instance.getVideosForSource(index, mode: mode)\n                } else {\n                    // all\n                    videos = VideoList.instance.videos.sorted { $0.secondaryName < $1.secondaryName }\n                }\n\n                guard !videos.isEmpty else {\n                    debugLog(\"empty videos\")\n                    return nil\n                }\n\n                let menu = NSMenu()\n\n                var hasUnfavs = false\n                var hasFavs = false\n\n                // Add a unhide menu just for the hidden category\n                if let mode = VideoList.instance.modeFromPath(path) {\n                    if mode == .hidden {\n                        let item = NSMenuItem(title: \"Show videos\", action: #selector(showVideos(_:)), keyEquivalent: \"\")\n                        item.setIcons(\"eye\")\n                        menu.addItem(item)\n\n                        return menu\n                    }\n                }\n\n                // Add/remove favorites\n                if !videos.filter({ !PrefsVideos.favorites.contains($0.id) }).isEmpty {\n                    let item = NSMenuItem(title: \"Favorite videos\", action: #selector(favoriteVideos(_:)), keyEquivalent: \"\")\n                    item.setIcons(\"star.fill\")\n                    menu.addItem(item)\n                    hasUnfavs = true\n                }\n\n                if !videos.filter({ PrefsVideos.favorites.contains($0.id) }).isEmpty {\n                    let item = NSMenuItem(title: \"Unfavorite videos\", action: #selector(unfavoriteVideos(_:)), keyEquivalent: \"\")\n                    item.setIcons(\"star\")\n                    menu.addItem(item)\n                    hasFavs = true\n                }\n\n                // Don't show the hide videos option if we only have favs in that list\n                if !(hasFavs && !hasUnfavs) {\n                    menu.addItem(NSMenuItem.separator())\n\n                    let item = NSMenuItem(title: \"Hide videos\", action: #selector(hideVideos(_:)), keyEquivalent: \"\")\n                    item.setIcons(\"eye.slash\")\n                    menu.addItem(item)\n                }\n\n                // Do we have uncached videos in here ?\n                if !videos.filter({!$0.isAvailableOffline}).isEmpty {\n                    menu.addItem(NSMenuItem.separator())\n                    let item = NSMenuItem(title: \"Cache missing videos\", action: #selector(cacheMissingVideos(_:)), keyEquivalent: \"\")\n                    item.setIcons(\"arrow.down.circle\")\n                    menu.addItem(item)\n                }\n\n                if !videos.filter({ PrefsVideos.vibrance.keys.contains($0.id) }).isEmpty {\n                    let item = NSMenuItem(title: \"Reset vibrance\", action: #selector(resetVibrance(_:)), keyEquivalent: \"\")\n                    item.setIcons(\"slider.horizontal.3\")\n                    menu.addItem(item)\n                    hasFavs = true\n                }\n\n                return menu\n            }\n        }\n\n        return nil\n    }\n\n    @objc func cacheMissingVideos(_ sender: Any) {\n        if menuPath == \"\" {\n            errorLog(\"Right click cache missing with no menu\")\n            return\n        }\n\n        Cache.ensureDownload {\n            let videos = VideoList.instance.getVideosForPath(self.menuPath)\n\n            for video in videos.filter({ !$0.isAvailableOffline }) {\n                VideoManager.sharedInstance.queueDownload(video)\n            }\n        }\n    }\n\n    @objc func favoriteVideos(_ sender: Any) {\n        if menuPath == \"\" {\n            errorLog(\"Right click missing path\")\n            return\n        }\n        let videos = VideoList.instance.getVideosForPath(self.menuPath)\n\n        for video in videos.filter({ !PrefsVideos.favorites.contains($0.id) }) {\n            PrefsVideos.favorites.append(video.id)\n        }\n        windowController!.updateViewInPlace()\n    }\n\n    @objc func unfavoriteVideos(_ sender: Any) {\n        if menuPath == \"\" {\n            errorLog(\"Right click missing path\")\n            return\n        }\n        let videos = VideoList.instance.getVideosForPath(self.menuPath)\n\n        for video in videos.filter({ PrefsVideos.favorites.contains($0.id) }) {\n            PrefsVideos.favorites.remove(at: PrefsVideos.favorites.firstIndex(of: video.id)!)\n        }\n        windowController!.updateViewInPlace()\n    }\n\n    @objc func showVideos(_ sender: Any) {\n        if menuPath == \"\" {\n            errorLog(\"Right click missing path\")\n            return\n        }\n        let videos = VideoList.instance.getVideosForPath(self.menuPath)\n\n        for video in videos.filter({ PrefsVideos.hidden.contains($0.id) }) {\n            PrefsVideos.hidden.remove(at: PrefsVideos.hidden.firstIndex(of: video.id)!)\n        }\n\n        // We need to reload our sidebar\n        // Sidebar.instance.refreshVideos()\n        sidebarOutlineView.reloadData()\n        sidebarOutlineView.expandItem(nil, expandChildren: true)\n        sidebarOutlineView.selectRowIndexes([1], byExtendingSelection: false)\n    }\n\n    @objc func hideVideos(_ sender: Any) {\n        if menuPath == \"\" {\n            errorLog(\"Right click missing path\")\n            return\n        }\n        let videos = VideoList.instance.getVideosForPath(self.menuPath)\n\n        for video in videos.filter({ !PrefsVideos.hidden.contains($0.id) }) {\n            PrefsVideos.hidden.append(video.id)\n        }\n\n        // We need to reload our sidebar\n        // Sidebar.instance.refreshVideos()\n        sidebarOutlineView.reloadData()\n        sidebarOutlineView.expandItem(nil, expandChildren: true)\n        sidebarOutlineView.selectRowIndexes([1], byExtendingSelection: false)\n    }\n    \n    \n\n    @objc func resetVibrance(_ sender: Any) {\n        if menuPath == \"\" {\n            errorLog(\"Right click missing path\")\n            return\n        }\n        let videos = VideoList.instance.getVideosForPath(self.menuPath)\n\n        for video in videos.filter({ PrefsVideos.vibrance.keys.contains($0.id) }) {\n            PrefsVideos.vibrance.removeValue(forKey: video.id)\n        }\n\n        windowController!.updateViewInPlace()\n    }\n}*/\n"
  },
  {
    "path": "Resources/MainUI/SidebarViewController.xib",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.Cocoa.XIB\" version=\"3.0\" toolsVersion=\"21225\" targetRuntime=\"MacOSX.Cocoa\" propertyAccessControl=\"none\" useAutolayout=\"YES\" customObjectInstantitationMethod=\"direct\">\n    <dependencies>\n        <deployment identifier=\"macosx\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.CocoaPlugin\" version=\"21225\"/>\n        <capability name=\"documents saved in the Xcode 8 format\" minToolsVersion=\"8.0\"/>\n    </dependencies>\n    <objects>\n        <customObject id=\"-2\" userLabel=\"File's Owner\" customClass=\"SidebarViewController\" customModule=\"Aerial\" customModuleProvider=\"target\">\n            <connections>\n                <outlet property=\"closeButton\" destination=\"iG6-m2-MeH\" id=\"OMi-5P-xSx\"/>\n                <outlet property=\"downloadCancelButton\" destination=\"RHI-PX-xtL\" id=\"mbQ-uJ-uAR\"/>\n                <outlet property=\"downloadIndicator\" destination=\"auW-RO-pTq\" id=\"vPt-YT-jkJ\"/>\n                <outlet property=\"downloadIndicatorLabel\" destination=\"K2f-cj-rKz\" id=\"cWX-Zq-hvz\"/>\n                <outlet property=\"downloadIndicatorProgress\" destination=\"JMH-1C-Qj3\" id=\"TpN-hW-IhO\"/>\n                <outlet property=\"sidebarOutlineView\" destination=\"ciZ-oy-meK\" id=\"es9-1g-Jl9\"/>\n                <outlet property=\"view\" destination=\"Hz6-mo-xeY\" id=\"0bl-1N-x8E\"/>\n            </connections>\n        </customObject>\n        <customObject id=\"-1\" userLabel=\"First Responder\" customClass=\"FirstResponder\"/>\n        <customObject id=\"-3\" userLabel=\"Application\" customClass=\"NSObject\"/>\n        <customView id=\"Hz6-mo-xeY\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"220\" height=\"530\"/>\n            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n            <subviews>\n                <stackView distribution=\"fill\" orientation=\"vertical\" alignment=\"leading\" spacing=\"0.0\" horizontalStackHuggingPriority=\"249.99998474121094\" verticalStackHuggingPriority=\"249.99998474121094\" horizontalCompressionResistancePriority=\"75\" verticalCompressionResistancePriority=\"75\" detachesHiddenViews=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"f2Y-mM-64d\">\n                    <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"220\" height=\"112\"/>\n                    <subviews>\n                        <visualEffectView verticalCompressionResistancePriority=\"75\" blendingMode=\"behindWindow\" material=\"sidebar\" state=\"followsWindowActiveState\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"auW-RO-pTq\">\n                            <rect key=\"frame\" x=\"0.0\" y=\"50\" width=\"220\" height=\"62\"/>\n                            <subviews>\n                                <progressIndicator wantsLayer=\"YES\" maxValue=\"100\" doubleValue=\"65\" style=\"bar\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"JMH-1C-Qj3\">\n                                    <rect key=\"frame\" x=\"10\" y=\"17\" width=\"166\" height=\"20\"/>\n                                </progressIndicator>\n                                <button toolTip=\"Cancel downloads\" wantsLayer=\"YES\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"RHI-PX-xtL\">\n                                    <rect key=\"frame\" x=\"186\" y=\"17\" width=\"24\" height=\"19\"/>\n                                    <buttonCell key=\"cell\" type=\"roundRect\" bezelStyle=\"roundedRect\" image=\"NSStopProgressFreestandingTemplate\" imagePosition=\"only\" alignment=\"center\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"Rbd-h3-LKQ\">\n                                        <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                                        <font key=\"font\" metaFont=\"cellTitle\"/>\n                                    </buttonCell>\n                                    <connections>\n                                        <action selector=\"cancelDownloads:\" target=\"-2\" id=\"fiO-rg-oOK\"/>\n                                    </connections>\n                                </button>\n                                <box verticalHuggingPriority=\"750\" boxType=\"separator\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"yJV-u1-aKe\">\n                                    <rect key=\"frame\" x=\"0.0\" y=\"59\" width=\"220\" height=\"5\"/>\n                                </box>\n                                <textField wantsLayer=\"YES\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"K2f-cj-rKz\">\n                                    <rect key=\"frame\" x=\"78\" y=\"42\" width=\"65\" height=\"14\"/>\n                                    <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" alignment=\"center\" title=\"Test blabla\" id=\"Wa0-N8-Wd8\">\n                                        <font key=\"font\" metaFont=\"smallSystem\"/>\n                                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    </textFieldCell>\n                                </textField>\n                            </subviews>\n                            <constraints>\n                                <constraint firstAttribute=\"trailing\" secondItem=\"RHI-PX-xtL\" secondAttribute=\"trailing\" constant=\"10\" id=\"0HV-1z-75p\"/>\n                                <constraint firstItem=\"RHI-PX-xtL\" firstAttribute=\"leading\" secondItem=\"JMH-1C-Qj3\" secondAttribute=\"trailing\" constant=\"10\" id=\"1rK-KG-c7F\"/>\n                                <constraint firstItem=\"K2f-cj-rKz\" firstAttribute=\"top\" secondItem=\"auW-RO-pTq\" secondAttribute=\"top\" constant=\"6\" id=\"5fS-zS-fXo\"/>\n                                <constraint firstAttribute=\"bottom\" secondItem=\"RHI-PX-xtL\" secondAttribute=\"bottom\" constant=\"18\" id=\"DVh-IB-Chc\"/>\n                                <constraint firstItem=\"JMH-1C-Qj3\" firstAttribute=\"top\" secondItem=\"K2f-cj-rKz\" secondAttribute=\"bottom\" constant=\"6\" id=\"EjY-N9-3LK\"/>\n                                <constraint firstItem=\"yJV-u1-aKe\" firstAttribute=\"top\" secondItem=\"auW-RO-pTq\" secondAttribute=\"top\" id=\"Per-zt-uuH\"/>\n                                <constraint firstItem=\"yJV-u1-aKe\" firstAttribute=\"leading\" secondItem=\"auW-RO-pTq\" secondAttribute=\"leading\" id=\"ehx-vN-jS0\"/>\n                                <constraint firstItem=\"JMH-1C-Qj3\" firstAttribute=\"leading\" secondItem=\"auW-RO-pTq\" secondAttribute=\"leading\" constant=\"10\" id=\"k0v-MG-laN\"/>\n                                <constraint firstItem=\"RHI-PX-xtL\" firstAttribute=\"centerY\" secondItem=\"JMH-1C-Qj3\" secondAttribute=\"centerY\" id=\"ubp-dE-RxJ\"/>\n                                <constraint firstItem=\"K2f-cj-rKz\" firstAttribute=\"centerX\" secondItem=\"auW-RO-pTq\" secondAttribute=\"centerX\" id=\"vzJ-zk-RB2\"/>\n                                <constraint firstAttribute=\"trailing\" secondItem=\"yJV-u1-aKe\" secondAttribute=\"trailing\" id=\"xzf-eI-FZx\"/>\n                            </constraints>\n                        </visualEffectView>\n                        <visualEffectView blendingMode=\"behindWindow\" material=\"sidebar\" state=\"followsWindowActiveState\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"6Ib-Fy-Cz1\">\n                            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"220\" height=\"50\"/>\n                            <subviews>\n                                <button wantsLayer=\"YES\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"iG6-m2-MeH\">\n                                    <rect key=\"frame\" x=\"4\" y=\"4\" width=\"212\" height=\"42\"/>\n                                    <buttonCell key=\"cell\" type=\"push\" title=\"Close\" bezelStyle=\"rounded\" alignment=\"center\" controlSize=\"large\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"tJZ-94-UZk\">\n                                        <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                        <string key=\"keyEquivalent\" base64-UTF8=\"YES\">\nGw\n</string>\n                                    </buttonCell>\n                                    <connections>\n                                        <action selector=\"closeButton:\" target=\"-2\" id=\"nLz-wy-pEn\"/>\n                                    </connections>\n                                </button>\n                            </subviews>\n                            <constraints>\n                                <constraint firstItem=\"iG6-m2-MeH\" firstAttribute=\"leading\" secondItem=\"6Ib-Fy-Cz1\" secondAttribute=\"leading\" constant=\"10\" id=\"Grz-A6-Nha\"/>\n                                <constraint firstAttribute=\"bottom\" secondItem=\"iG6-m2-MeH\" secondAttribute=\"bottom\" constant=\"10\" id=\"P2c-gr-EeM\"/>\n                                <constraint firstAttribute=\"trailing\" secondItem=\"iG6-m2-MeH\" secondAttribute=\"trailing\" constant=\"10\" id=\"inC-ph-yBf\"/>\n                                <constraint firstItem=\"iG6-m2-MeH\" firstAttribute=\"top\" secondItem=\"6Ib-Fy-Cz1\" secondAttribute=\"top\" constant=\"10\" id=\"vJq-4b-wQM\"/>\n                            </constraints>\n                        </visualEffectView>\n                    </subviews>\n                    <constraints>\n                        <constraint firstAttribute=\"trailing\" secondItem=\"auW-RO-pTq\" secondAttribute=\"trailing\" id=\"0Qs-Yg-8xM\"/>\n                        <constraint firstAttribute=\"width\" constant=\"220\" id=\"2Ta-Hk-Rdk\"/>\n                        <constraint firstItem=\"auW-RO-pTq\" firstAttribute=\"top\" secondItem=\"f2Y-mM-64d\" secondAttribute=\"top\" id=\"Ck3-Ut-wdv\"/>\n                        <constraint firstItem=\"auW-RO-pTq\" firstAttribute=\"leading\" secondItem=\"f2Y-mM-64d\" secondAttribute=\"leading\" id=\"NjE-2f-FQP\"/>\n                        <constraint firstAttribute=\"bottom\" secondItem=\"6Ib-Fy-Cz1\" secondAttribute=\"bottom\" id=\"QYA-k5-xyw\"/>\n                        <constraint firstAttribute=\"trailing\" secondItem=\"6Ib-Fy-Cz1\" secondAttribute=\"trailing\" id=\"VqG-BK-yOE\"/>\n                        <constraint firstItem=\"6Ib-Fy-Cz1\" firstAttribute=\"leading\" secondItem=\"f2Y-mM-64d\" secondAttribute=\"leading\" id=\"cam-4A-QPR\"/>\n                        <constraint firstItem=\"6Ib-Fy-Cz1\" firstAttribute=\"top\" secondItem=\"auW-RO-pTq\" secondAttribute=\"bottom\" id=\"hGW-lQ-FQY\"/>\n                    </constraints>\n                    <visibilityPriorities>\n                        <integer value=\"1000\"/>\n                        <integer value=\"1000\"/>\n                    </visibilityPriorities>\n                    <customSpacing>\n                        <real value=\"3.4028234663852886e+38\"/>\n                        <real value=\"3.4028234663852886e+38\"/>\n                    </customSpacing>\n                </stackView>\n                <scrollView borderType=\"none\" autohidesScrollers=\"YES\" horizontalLineScroll=\"30\" horizontalPageScroll=\"10\" verticalLineScroll=\"30\" verticalPageScroll=\"10\" usesPredominantAxisScrolling=\"NO\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"K2J-Hc-39v\">\n                    <rect key=\"frame\" x=\"0.0\" y=\"112\" width=\"220\" height=\"418\"/>\n                    <clipView key=\"contentView\" drawsBackground=\"NO\" id=\"8uE-tR-c23\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"220\" height=\"418\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <subviews>\n                            <outlineView focusRingType=\"none\" verticalHuggingPriority=\"750\" allowsExpansionToolTips=\"YES\" columnAutoresizingStyle=\"lastColumnOnly\" tableStyle=\"sourceList\" selectionHighlightStyle=\"sourceList\" columnReordering=\"NO\" columnResizing=\"NO\" multipleSelection=\"NO\" autosaveColumns=\"NO\" rowHeight=\"30\" rowSizeStyle=\"automatic\" viewBased=\"YES\" floatsGroupRows=\"NO\" outlineTableColumn=\"axa-le-hBc\" id=\"ciZ-oy-meK\" customClass=\"SidebarOutlineView\" customModule=\"Aerial\" customModuleProvider=\"target\">\n                                <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"220\" height=\"418\"/>\n                                <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                                <size key=\"intercellSpacing\" width=\"3\" height=\"0.0\"/>\n                                <color key=\"backgroundColor\" name=\"_sourceListBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                <color key=\"gridColor\" name=\"gridColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                <tableColumns>\n                                    <tableColumn width=\"188\" minWidth=\"16\" maxWidth=\"1000\" id=\"axa-le-hBc\">\n                                        <tableHeaderCell key=\"headerCell\" lineBreakMode=\"truncatingTail\" borderStyle=\"border\">\n                                            <color key=\"textColor\" name=\"headerTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                            <color key=\"backgroundColor\" name=\"headerColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                        </tableHeaderCell>\n                                        <textFieldCell key=\"dataCell\" controlSize=\"large\" lineBreakMode=\"truncatingTail\" selectable=\"YES\" editable=\"YES\" title=\"Text Cell\" id=\"kdT-TK-rYx\">\n                                            <font key=\"font\" metaFont=\"system\"/>\n                                            <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                            <color key=\"backgroundColor\" name=\"controlBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                        </textFieldCell>\n                                        <tableColumnResizingMask key=\"resizingMask\" resizeWithTable=\"YES\" userResizable=\"YES\"/>\n                                        <prototypeCellViews>\n                                            <tableCellView identifier=\"HeaderCell\" id=\"nj3-9L-guH\">\n                                                <rect key=\"frame\" x=\"11\" y=\"0.0\" width=\"197\" height=\"24\"/>\n                                                <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                                                <subviews>\n                                                    <textField verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Tvb-VO-ifT\">\n                                                        <rect key=\"frame\" x=\"0.0\" y=\"6\" width=\"210\" height=\"16\"/>\n                                                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\"/>\n                                                        <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"truncatingTail\" enabled=\"NO\" sendsActionOnEndEditing=\"YES\" title=\"HEADER CELL\" id=\"IxU-vc-Rzz\">\n                                                            <font key=\"font\" metaFont=\"system\"/>\n                                                            <color key=\"textColor\" name=\"headerColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                            <color key=\"backgroundColor\" name=\"controlColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                        </textFieldCell>\n                                                    </textField>\n                                                </subviews>\n                                                <connections>\n                                                    <outlet property=\"textField\" destination=\"Tvb-VO-ifT\" id=\"EUJ-HM-Ac3\"/>\n                                                </connections>\n                                            </tableCellView>\n                                            <tableCellView identifier=\"DataCell\" id=\"g4S-ge-F2f\">\n                                                <rect key=\"frame\" x=\"11\" y=\"24\" width=\"197\" height=\"30\"/>\n                                                <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                                                <subviews>\n                                                    <textField verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"iXR-Im-0Vq\">\n                                                        <rect key=\"frame\" x=\"32\" y=\"8\" width=\"165\" height=\"17\"/>\n                                                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\"/>\n                                                        <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"truncatingTail\" sendsActionOnEndEditing=\"YES\" title=\"Table View Cell\" id=\"aIc-4e-tVY\">\n                                                            <font key=\"font\" metaFont=\"system\" size=\"15\"/>\n                                                            <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                            <color key=\"backgroundColor\" name=\"controlColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                        </textFieldCell>\n                                                    </textField>\n                                                    <imageView wantsLayer=\"YES\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"5UG-iz-17w\">\n                                                        <rect key=\"frame\" x=\"10\" y=\"5\" width=\"16.5\" height=\"21\"/>\n                                                        <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\"/>\n                                                        <imageCell key=\"cell\" controlSize=\"large\" refusesFirstResponder=\"YES\" imageScaling=\"proportionallyDown\" image=\"leaf\" catalog=\"system\" id=\"T8g-jH-RDt\"/>\n                                                    </imageView>\n                                                </subviews>\n                                                <connections>\n                                                    <outlet property=\"imageView\" destination=\"5UG-iz-17w\" id=\"PfA-fO-i6m\"/>\n                                                    <outlet property=\"textField\" destination=\"iXR-Im-0Vq\" id=\"iYm-oi-apc\"/>\n                                                </connections>\n                                            </tableCellView>\n                                        </prototypeCellViews>\n                                    </tableColumn>\n                                </tableColumns>\n                            </outlineView>\n                        </subviews>\n                        <nil key=\"backgroundColor\"/>\n                    </clipView>\n                    <scroller key=\"horizontalScroller\" hidden=\"YES\" wantsLayer=\"YES\" verticalHuggingPriority=\"750\" horizontal=\"YES\" id=\"xTi-ZQ-NDh\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"402\" width=\"220\" height=\"16\"/>\n                        <autoresizingMask key=\"autoresizingMask\"/>\n                    </scroller>\n                    <scroller key=\"verticalScroller\" hidden=\"YES\" wantsLayer=\"YES\" verticalHuggingPriority=\"750\" horizontal=\"NO\" id=\"vrX-X6-xUy\">\n                        <rect key=\"frame\" x=\"224\" y=\"17\" width=\"15\" height=\"102\"/>\n                        <autoresizingMask key=\"autoresizingMask\"/>\n                    </scroller>\n                </scrollView>\n            </subviews>\n            <constraints>\n                <constraint firstItem=\"f2Y-mM-64d\" firstAttribute=\"leading\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"leading\" id=\"BKm-ZI-9lL\"/>\n                <constraint firstAttribute=\"trailing\" secondItem=\"f2Y-mM-64d\" secondAttribute=\"trailing\" id=\"E8o-fN-PE6\"/>\n                <constraint firstAttribute=\"trailing\" secondItem=\"K2J-Hc-39v\" secondAttribute=\"trailing\" id=\"Tg6-LK-wuO\"/>\n                <constraint firstAttribute=\"bottom\" secondItem=\"f2Y-mM-64d\" secondAttribute=\"bottom\" id=\"VZQ-w2-Q8e\"/>\n                <constraint firstItem=\"K2J-Hc-39v\" firstAttribute=\"leading\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"leading\" id=\"YId-aJ-NBL\"/>\n                <constraint firstItem=\"K2J-Hc-39v\" firstAttribute=\"top\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"top\" id=\"oDi-Rx-J4Q\"/>\n                <constraint firstItem=\"f2Y-mM-64d\" firstAttribute=\"top\" secondItem=\"K2J-Hc-39v\" secondAttribute=\"bottom\" id=\"t8n-sA-OJB\"/>\n            </constraints>\n            <point key=\"canvasLocation\" x=\"-85\" y=\"218\"/>\n        </customView>\n    </objects>\n    <resources>\n        <image name=\"NSStopProgressFreestandingTemplate\" width=\"20\" height=\"20\"/>\n        <image name=\"leaf\" catalog=\"system\" width=\"16\" height=\"14\"/>\n    </resources>\n</document>\n"
  },
  {
    "path": "Resources/MainUI/VideosViewController.swift",
    "content": "//\n//  VideosViewController.swift\n//  Aerial\n//\n//  Created by Guillaume Louel on 15/07/2020.\n//  Copyright © 2020 Guillaume Louel. All rights reserved.\n//\n\nimport Cocoa\nimport AVKit\n\n// swiftlint:disable:next type_body_length\nclass VideosViewController: NSViewController {\n    // Top rotation view\n    @IBOutlet var rotationView: NSView!\n    @IBOutlet var rotationPopup: NSPopUpButton!\n    @IBOutlet var rotationImage: NSImageView!\n    @IBOutlet var rotationCacheNow: NSButton!\n\n    @IBOutlet var rotationSecondaryPopup: NSPopUpButton!\n    @IBOutlet var rotationSecondaryMenu: NSMenu!\n\n    @IBOutlet var videoListTableView: NSTableView!\n    @IBOutlet var videoListRuntimeLabel: NSTextField!\n\n    @IBOutlet var heroPlayerView: AVPlayerView!\n    @IBOutlet var heroImageView: NSImageView!\n\n    @IBOutlet var titleLabel: NSTextField!\n    @IBOutlet var locationLabel: NSTextField!\n    @IBOutlet var durationLabel: NSTextField!\n\n    @IBOutlet var sourceLabel: NSTextField!\n    @IBOutlet var formatLabel: NSTextField!\n\n    @IBOutlet var timeImageView: NSImageView!\n    @IBOutlet var sceneTypeImageView: NSImageView!\n\n    @IBOutlet var downloadButton: NSButton!\n    @IBOutlet var hideButton: NSButton!\n    @IBOutlet var showButton: NSButton!\n\n    @IBOutlet var isCachedImageView: NSImageView!\n\n    @IBOutlet var vibrancyLabel: NSTextField!\n    @IBOutlet var vibrancySlider: NSSlider!\n\n    @IBOutlet var playbackSpeedLabel: NSTextField!\n\n    @IBOutlet var playbackSpeedSlider: NSSlider!\n\n    var path: String?\n    var mode: String?\n\n    var currentVibrancy: Double = 0\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n\n        rotationView.isHidden = false\n\n        // Our video list\n        videoListTableView.delegate = self\n        videoListTableView.dataSource = self\n\n        // Our large player view\n        heroPlayerView.player = AVPlayer()\n        heroPlayerView.controlsStyle = .none\n        if #available(OSX 10.10, *) {\n            heroPlayerView.videoGravity = .resizeAspectFill\n        }\n\n        downloadButton.setIcons(\"arrow.down.circle\")\n        hideButton.setIcons(\"eye.slash\")\n        showButton.setIcons(\"eye\")\n        setShadows()\n        fixIcons()\n\n        updateVideoView()\n        updateRotationMenu()\n\n        // This needs cleanup someday\n        rotationSecondaryPopup.isHidden = true\n        rotationCacheNow.isHidden = true\n    }\n\n    @objc func playerItemDidReachEnd(_ aNotification: Notification) {\n        debugLog(\"\\(self.description) played did reach end\")\n        debugLog(\"\\(self.description) notification: \\(aNotification)\")\n\n        debugLog(\"Rewinding video!\")\n        if let playerItem = aNotification.object as? AVPlayerItem {\n            playerItem.seek(to: CMTime.zero, completionHandler: nil)\n            heroPlayerView.player?.play()\n        }\n    }\n\n    // MARK: - UI init\n    /// Set the shadows for the various UI elements that needs them\n    func setShadows() {\n        // Drop shadow we use on the overlayed items\n        let shadow: NSShadow = NSShadow()\n        shadow.shadowBlurRadius = 2\n        shadow.shadowOffset = NSSize(width: 0, height: 3)\n        shadow.shadowColor = NSColor.black\n        // For images the height coordinates are reversed, obviously...\n        let imgShadow: NSShadow = NSShadow()\n        imgShadow.shadowBlurRadius = 2\n        imgShadow.shadowOffset = NSSize(width: 0, height: -3)\n        imgShadow.shadowColor = NSColor.black\n\n        titleLabel.shadow = shadow\n        locationLabel.shadow = shadow\n        durationLabel.shadow = shadow\n        hideButton.shadow = shadow\n        showButton.shadow = shadow\n        downloadButton.shadow = shadow\n        vibrancyLabel.shadow = shadow\n        vibrancySlider.shadow = shadow\n        playbackSpeedLabel.shadow = shadow\n        playbackSpeedSlider.shadow = shadow\n\n        timeImageView.shadow = imgShadow\n        sceneTypeImageView.shadow = imgShadow\n        isCachedImageView.shadow = imgShadow\n    }\n\n    /// Since we can't directly use SF Symbols, we use our own icon wrappers\n    func fixIcons() {\n        // rotationPopup.item(at: 0)?.setIcons(\"film\")\n        // rotationPopup.item(at: 1)?.setIcons(\"star\")\n        // rotationPopup.item(at: 2)?.setIcons(\"mappin.and.ellipse\")\n        // rotationPopup.item(at: 3)?.setIcons(\"clock\")\n        // rotationPopup.item(at: 4)?.setIcons(\"tram.fill\")\n        // rotationPopup.item(at: 5)?.setIcons(\"antenna.radiowaves.left.and.right\")\n        rotationImage.image = Aerial.helper.getAccentedSymbol(\"film\")\n        rotationCacheNow.setIcons(\"arrow.down.circle\")\n    }\n\n    func switchMainTo(filter: VideoList.FilterMode) {\n        switch filter {\n        case .location:\n            rotationPopup.selectItem(at: 2)\n        case .time:\n            rotationPopup.selectItem(at: 3)\n        case .scene:\n            rotationPopup.selectItem(at: 4)\n        case .source:\n            rotationPopup.selectItem(at: 5)\n        case .favorite:\n            rotationPopup.selectItem(at: 1)\n        case .hidden:\n            rotationPopup.selectItem(at: 6)\n        default:\n            rotationPopup.selectItem(at: 1)\n        }\n    }\n    /// Reload with a named path\n    /// This is used by the\n    func reloadPath(path: String) {\n        if let foundMode = VideoList.instance.modeFromPath(path) {\n            switchMainTo(filter: foundMode)\n\n            rotationPopupChange(rotationPopup)\n\n            let subpath = path.split(separator: \":\")[1]\n\n            //print(subpath)\n\n            // Very unswift\n            var index = 0\n            for item in VideoList.instance.getSources(mode: foundMode) {\n                if subpath == item {\n                    rotationSecondaryPopup.selectItem(at: index)\n                    rotationSecondaryPopupChange(rotationSecondaryPopup)\n                }\n                index += 1\n            }\n        }\n    }\n\n    /// Reload the video view for a given path\n    func reloadFor(path: String) {\n        self.path = path\n\n        updateRotationMenu()\n        updateRuntimeLabel()\n\n        // Reload data and scroll back up\n        if videoListTableView != nil {\n            videoListTableView.reloadData()\n            videoListTableView.selectRowIndexes([0], byExtendingSelection: false)\n            videoListTableView.scrollRowToVisible(0)\n\n            if videoListTableView.numberOfRows == 0 {\n                updateVideoView()\n            }\n        }\n    }\n\n    /// Update the total runtime for the current view\n    func updateRuntimeLabel() {\n        guard let path = self.path else {\n            videoListRuntimeLabel.stringValue = \"\"\n            return\n        }\n\n        // Grab all videos in the path\n        var videos: [AerialVideo]\n        if let mode = VideoList.instance.modeFromPath(path) {\n            let index = Int(path.split(separator: \":\")[1])!\n            videos = VideoList.instance.getVideosForSource(index, mode: mode)\n        } else {\n            // all\n            videos = VideoList.instance.videos.filter({ !PrefsVideos.hidden.contains($0.id) }).sorted { $0.secondaryName < $1.secondaryName }\n        }\n\n        // Calculate their duration in minutes\n        var duration: Double = 0\n        for video in videos {\n            duration += video.duration\n        }\n\n        let minutes: Int = Int(duration) / 60\n\n        var minutesString: String\n        if minutes < 2 {\n            minutesString = \"1 minute\"\n        } else {\n            minutesString = \"\\(minutes) minutes\"\n        }\n\n        // Update the label\n        if videos.isEmpty {\n            videoListRuntimeLabel.stringValue = \"\"\n        } else if videos.count == 1 {\n            videoListRuntimeLabel.stringValue = \"1 video, \\(minutesString)\"\n        } else {\n            videoListRuntimeLabel.stringValue = \"\\(videos.count) videos, \\(minutesString)\"\n        }\n    }\n\n    // MARK: - Rotation menu\n\n    /// Cache missing rotation now !\n    @IBAction func rotationCacheNowClick(_ sender: NSButton) {\n        Cache.ensureDownload {\n            for video in VideoList.instance.currentRotation().filter({ !$0.isAvailableOffline }) {\n                VideoManager.sharedInstance.queueDownload(video)\n            }\n        }\n    }\n\n    /// Main popup change event\n    @IBAction func rotationPopupChange(_ sender: NSPopUpButton) {\n\n        switch sender.indexOfSelectedItem {\n        case 0:\n            mode = \"all\"\n        case 1:\n            mode = \"favorites\"\n        case 2:\n            mode = \"location\"\n        case 3:\n            mode = \"time\"\n        case 4:\n            mode = \"scene\"\n        case 5:\n            mode = \"source\"\n        case 6:\n            mode = \"hidden\"\n        default:\n            mode = \"all\"\n        }\n\n        // Cascade to a secondary popup for the various filters\n        if mode == \"all\" || mode == \"favorites\" || mode == \"hidden\" {\n            rotationSecondaryPopup.isHidden = true\n            path = mode! + \":0\"\n            reloadFor(path: path!)\n        } else {\n            rotationSecondaryPopup.isHidden = false\n            updateRotationSecondaryMenu()\n        }\n    }\n\n    /// Secondary popup change event\n    @IBAction func rotationSecondaryPopupChange(_ sender: NSPopUpButton) {\n        // PrefsVideos.shouldPlayString = sender.selectedItem!.title\n        path = mode! + \":\\(sender.indexOfSelectedItem)\"\n        reloadFor(path: path!)\n    }\n\n    func updateRotationMenu() {\n        // rotationPopup.selectItem(at: PrefsVideos.intShouldPlay)\n\n        // Cascade to a secondary popup for the various filters\n       /* if PrefsVideos.shouldPlay == .everything || PrefsVideos.shouldPlay == .favorites {\n            rotationSecondaryPopup.isHidden = true\n        } else {\n            rotationSecondaryPopup.isHidden = false\n            // updateRotationSecondaryMenu()\n        }*/\n/*\n        if VideoList.instance.currentRotation().filter({ !$0.isAvailableOffline }).isEmpty {\n            rotationCacheNow.isHidden = true\n        } else {\n            rotationCacheNow.isHidden = false\n        }*/\n    }\n\n    func updateRotationSecondaryMenu() {\n        var filter: VideoList.FilterMode\n\n        filter = VideoList.instance.modeFromPath(mode!) ?? .location\n        rotationSecondaryPopup.removeAllItems()\n\n        // Very unswift\n        var index = 0\n        for item in VideoList.instance.getSources(mode: filter) {\n            rotationSecondaryPopup.addItem(withTitle: item)\n\n            index += 1\n        }\n\n        // We select the first one\n        if rotationSecondaryPopup.numberOfItems > 0 {\n            // PrefsVideos.shouldPlayString = rotationSecondaryPopup.itemTitle(at: 0)\n            rotationSecondaryPopup.selectItem(at: 0)\n            path = mode! + \":0\"\n            reloadFor(path: path!)\n        }\n    }\n\n    // MARK: - Video view\n    func updateVideoView() {\n        if let video = getSelectedVideo() {\n            debugLog(\"\\\"\\(video.id)\\\": \\\"sunrise\\\", // \\(video.name) - \\(video.secondaryName)\")\n            debugLog(\"\\\"\\(video.id)\\\": \\\"sunset\\\", // \\(video.name) - \\(video.secondaryName)\")\n            debugLog(\"\\\"\\(video.id)\\\": \\\"night\\\", // \\(video.name) - \\(video.secondaryName)\")\n\n            titleLabel.isHidden = false\n            locationLabel.isHidden = false\n            sourceLabel.isHidden = false\n            formatLabel.isHidden = false\n\n            titleLabel.stringValue = video.secondaryName\n            locationLabel.stringValue = video.name\n            sourceLabel.stringValue = video.source.name\n            formatLabel.stringValue = video.getCurrentFormat()\n\n            if PrefsVideos.hidden.contains(video.id) {\n                hideButton.isHidden = true\n                showButton.isHidden = false\n            } else {\n                hideButton.isHidden = false\n                showButton.isHidden = true\n            }\n\n            if video.isAvailableOffline {\n                // System settings crash under macOS 13 with HDR videos\n                if !Aerial.helper.canHDR() {\n                    if !Aerial.helper.underCompanion && (PrefsVideos.videoFormat == .v4KHDR || PrefsVideos.videoFormat == .v1080pHDR) {\n                        showImage(video)\n                    } else {\n                        showVideo(video)\n                    }\n                } else {\n                    showVideo(video)\n                }\n            } else {\n                showImage(video)\n            }\n\n            setTimeIcon(video)\n            setSceneIcon(video)\n        } else {\n            hideEverything()\n        }\n    }\n\n    func stopVideo() {\n        if let player = heroPlayerView.player {\n            debugLog(\"Stopping player\")\n            player.pause()\n        }\n    }\n\n    func updateDurationLabel(_ video: AerialVideo) {\n        let speed = PlaybackSpeed.forVideo(video.id)\n        if speed == 1 {\n            durationLabel.stringValue = \"Duration: \" + timeString(video.duration)\n        } else if speed > 1 {\n            durationLabel.stringValue = \"Duration(sped up): \" + timeString(video.duration/Double(speed))\n        } else {\n            durationLabel.stringValue = \"Duration(slowed down): \" + timeString(video.duration/Double(speed))\n        }\n    }\n\n    /// Show video player\n    func showVideo(_ video: AerialVideo) {\n        playbackSpeedLabel.isHidden = false\n        playbackSpeedSlider.isHidden = false\n\n        \n        heroPlayerView.isHidden = false\n        heroImageView.isHidden = true\n        isCachedImageView.isHidden = false\n\n        durationLabel.isHidden = false\n\n        updateDurationLabel(video)\n\n        downloadButton.isHidden = true\n\n        if let player = heroPlayerView.player {\n            let path = VideoList.instance.localPathFor(video: video)\n            debugLog(\"heropath : \\(path)\")\n\n            let asset = AVAsset(url: URL(fileURLWithPath: path))\n            let localitem = AVPlayerItem(asset: asset)\n\n            // Set slider for the playback speed\n            playbackSpeedSlider.doubleValue = Double(PlaybackSpeed.forVideo(video.id))\n\n            // Vibrancy filter requires 10.14, and doesn't work on HDR content\n            if #available(OSX 10.14, *), !video.isHDR() {\n                if PrefsVideos.allowPerVideoVibrance {\n                    vibrancyLabel.isHidden = false\n                    vibrancySlider.isHidden = false\n                    if let value = PrefsVideos.vibrance[video.id] {\n                        vibrancySlider.doubleValue = value\n                    } else {\n                        vibrancySlider.doubleValue = 0.0\n                    }\n                    if vibrancySlider.doubleValue == 0 {\n                        currentVibrancy = PrefsVideos.globalVibrance\n                    } else {\n                        currentVibrancy = vibrancySlider.doubleValue\n                    }\n                } else {\n                    vibrancyLabel.isHidden = true\n                    vibrancySlider.isHidden = true\n                }\n\n                let filter = CIFilter(name: \"CIVibrance\")!\n                localitem.videoComposition = AVVideoComposition(asset: asset, applyingCIFiltersWithHandler: { request in\n                    let source = request.sourceImage.clampedToExtent()\n                    filter.setValue(source, forKey: kCIInputImageKey)\n                    filter.setValue(self.currentVibrancy, forKey: kCIInputAmountKey)\n                    let output = filter.outputImage\n\n                    request.finish(with: output!, context: nil)\n                })\n            } else {\n                vibrancyLabel.isHidden = true\n                vibrancySlider.isHidden = true\n            }\n\n            player.replaceCurrentItem(with: localitem)\n            // We may not auto play the video\n            if PrefsAdvanced.autoPlayPreviews {\n                player.play()\n\n                // Set the playback speed if changed, it defaults to normal speed if not overriden\n                player.rate = PlaybackSpeed.forVideo(video.id)\n            }\n\n            // Set notification...\n            NotificationCenter.default.addObserver(self,\n                                           selector: #selector(playerItemDidReachEnd(_:)),\n                                           name: NSNotification.Name.AVPlayerItemDidPlayToEndTime,\n                                           object: localitem)\n        }\n    }\n\n    /// Show image\n    func showImage(_ video: AerialVideo) {\n        heroPlayerView.isHidden = true\n        heroImageView.isHidden = false\n        isCachedImageView.isHidden = true\n\n        vibrancyLabel.isHidden = true\n        vibrancySlider.isHidden = true\n\n        playbackSpeedLabel.isHidden = true\n        playbackSpeedSlider.isHidden = true\n\n        durationLabel.isHidden = true\n        if PrefsCache.enableManagement {\n            downloadButton.isHidden = true  // Always hide in managed mode\n        } else {\n            downloadButton.isHidden = false\n        }\n\n        // Clear up any playing video\n        if let player = heroPlayerView.player {\n            player.replaceCurrentItem(with: nil)\n            player.pause()\n        }\n\n        heroImageView.imageScaling = .scaleProportionallyDown\n\n        Thumbnails.getLarge(forVideo: video) { [weak self] (img) in\n            guard let _ = self else { return }\n            if let img = img {\n                self!.heroImageView.image = img\n            } else {\n                self!.heroImageView.image = nil\n            }\n        }\n    }\n\n    /// Hide everything !\n    func hideEverything() {\n        titleLabel.isHidden = true\n        locationLabel.isHidden = true\n        durationLabel.isHidden = true\n        sourceLabel.isHidden = true\n        formatLabel.isHidden = true\n\n        heroPlayerView.isHidden = true\n        heroImageView.isHidden = true\n        isCachedImageView.isHidden = true\n\n        downloadButton.isHidden = true\n        hideButton.isHidden = true\n        showButton.isHidden = true\n\n        vibrancyLabel.isHidden = true\n        vibrancySlider.isHidden = true\n\n        // Clear up any playing video\n        if let player = heroPlayerView.player {\n            player.replaceCurrentItem(with: nil)\n            player.pause()\n        }\n\n        setTimeIcon(nil)\n        setSceneIcon(nil)\n    }\n\n    @IBAction func vibrancySliderChange(_ sender: NSSlider) {\n        currentVibrancy = vibrancySlider.doubleValue\n        PrefsVideos.vibrance[getSelectedVideo()!.id] = vibrancySlider.doubleValue\n    }\n\n    @IBAction func playbackSpeedSliderChange(_ sender: NSSlider) {\n        PlaybackSpeed.update(video: getSelectedVideo()!.id,\n                             value: playbackSpeedSlider.floatValue)\n\n        // Make sure we update the duration\n        updateDurationLabel(getSelectedVideo()!)\n        if PrefsAdvanced.autoPlayPreviews {\n            if heroPlayerView.player?.rate != 0 {\n                heroPlayerView.player?.rate = PlaybackSpeed.forVideo(getSelectedVideo()!.id)\n            }\n        }\n    }\n\n    // MARK: - Helpers\n    func timeString(_ double: Double) -> String {\n        let intValue = Int(double)\n        if intValue % 60 < 10 {\n            return String(intValue / 60) + \":0\" + String(intValue % 60)\n        } else {\n            return String(intValue / 60) + \":\" + String(intValue % 60)\n        }\n    }\n\n    func getSelectedVideo() -> AerialVideo? {\n        if let path = path {\n            if videoListTableView.selectedRow > -1 {\n                if let mode = VideoList.instance.modeFromPath(path) {\n                    let index = Int(path.split(separator: \":\")[1])!\n                    if index >= 0 && videoListTableView.selectedRow >= 0 {\n                        return VideoList.instance.getVideoForSource(index, item: videoListTableView.selectedRow, mode: mode)\n                    }\n                } else {\n                    // all\n                    //print(VideoList.instance.videos.count)\n                    if VideoList.instance.videos.count > 0 {\n                        return VideoList.instance.videos\n                            .filter({ !PrefsVideos.hidden.contains($0.id) })\n                            .sorted { $0.secondaryName < $1.secondaryName }[videoListTableView.selectedRow]\n                    }\n                }\n            }\n        }\n\n        return nil\n    }\n\n    // Set the time icon\n    func setTimeIcon(_ video: AerialVideo?) {\n        guard let tvideo = video else {\n            timeImageView.image = nil\n            return\n        }\n\n        switch tvideo.timeOfDay {\n        case \"sunset\":\n            timeImageView.image = Aerial.helper.getSymbol(\"sunset\")\n        case \"sunrise\":\n            timeImageView.image = Aerial.helper.getSymbol(\"sunrise\")\n        case \"night\":\n            timeImageView.image = Aerial.helper.getSymbol(\"moon.stars\")\n        default:    // day\n            timeImageView.image = Aerial.helper.getSymbol(\"sun.max\")\n        }\n    }\n\n    // Set the scene icon (landscape...)\n    func setSceneIcon(_ video: AerialVideo?) {\n        guard let tvideo = video else {\n            sceneTypeImageView.image = nil\n            return\n        }\n\n        switch tvideo.scene {\n        case .nature:\n            sceneTypeImageView.image = Aerial.helper.getSymbol(\"leaf\")\n        case .beach:\n            sceneTypeImageView.image = Aerial.helper.getSymbol(\"leaf\")\n        case .countryside:\n            sceneTypeImageView.image = Aerial.helper.getSymbol(\"leaf\")\n        case .city:\n            sceneTypeImageView.image = Aerial.helper.getSymbol(\"tram.fill\")\n        case .space:\n            sceneTypeImageView.image = Aerial.helper.getSymbol(\"sparkles\")\n        case .sea:\n            sceneTypeImageView.image = Aerial.helper.getSymbol(\"helm\")\n        }\n    }\n\n    // MARK: - Buttons\n    @IBAction func downloadButton(_ sender: Any) {\n        downloadButton.isHidden = true\n        if let video = getSelectedVideo() {\n            let videoManager = VideoManager.sharedInstance\n            Cache.ensureDownload {\n                videoManager.queueDownload(video)\n            }\n        }\n    }\n\n    @IBAction func hideButtonClick(_ sender: Any) {\n        if let video = getSelectedVideo() {\n            PrefsVideos.hidden.append(video.id)\n            hideButton.isHidden = true\n            showButton.isHidden = false\n            updateInPlace()\n        }\n    }\n\n    @IBAction func showButtonClick(_ sender: Any) {\n        if let video = getSelectedVideo() {\n            if let index = PrefsVideos.hidden.firstIndex(of: video.id) {\n                PrefsVideos.hidden.remove(at: index)\n                hideButton.isHidden = false\n                showButton.isHidden = true\n                updateInPlace()\n            } else {\n                errorLog(\"Can't find video when unhiding, please report\")\n            }\n        }\n    }\n\n    func updateInPlace() {\n        let row = videoListTableView.selectedRow\n\n        if videoListTableView != nil {\n            videoListTableView.reloadData()\n            videoListTableView.selectRowIndexes([row], byExtendingSelection: false)\n        }\n        updateRotationMenu()\n    }\n}\n\nextension VideosViewController: NSTableViewDataSource {\n    func numberOfRows(in tableView: NSTableView) -> Int {\n        guard let path = path else {\n            return 0\n        }\n\n        //print(\"nor path : \" + path)\n\n        if let mode = VideoList.instance.modeFromPath(path) {\n            let index = Int(path.split(separator: \":\")[1])!\n            return VideoList.instance.getVideosCountForSource(index, mode: mode)\n        } else {\n            // all\n            return VideoList.instance.videos.filter({ !PrefsVideos.hidden.contains($0.id) }).count\n        }\n    }\n}\n\nextension VideosViewController: NSTableViewDelegate {\n    func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {\n        guard let path = path else {\n            return nil\n        }\n\n        //print(\"tv path : \" + path)\n\n        var video: AerialVideo\n        if let mode = VideoList.instance.modeFromPath(path) {\n            let index = Int(path.split(separator: \":\")[1])!\n            video = VideoList.instance.getVideoForSource(index, item: row, mode: mode)\n        } else {\n            // all\n            video = VideoList.instance.videos.filter({ !PrefsVideos.hidden.contains($0.id) }).sorted { $0.secondaryName < $1.secondaryName }[row]\n        }\n\n        if let cell = tableView.makeView(withIdentifier:\n            NSUserInterfaceItemIdentifier(rawValue: \"ImageCellID\"), owner: nil) as? VideoCellView {\n            cell.video = video\n            cell.label.stringValue = video.secondaryName\n            cell.checkButton.state = PrefsVideos.favorites.contains(video.id) ? .on : .off\n\n            if PrefsVideos.hidden.contains(video.id) {\n                cell.checkButton.isHidden = true\n            } else {\n                cell.checkButton.isHidden = false\n            }\n\n            if PrefsCache.enableManagement {\n                cell.downloadButton.isHidden = true\n            } else {\n                cell.downloadButton.isHidden = video.isAvailableOffline\n            }\n\n            Thumbnails.get(forVideo: video) { [weak self] (img) in\n                guard let _ = self else { return }\n                if let img = img {\n                    cell.thumbView.image = img\n                } else {\n                    cell.thumbView.image = nil\n                }\n            }\n\n            return cell\n        }\n        return nil\n    }\n\n    func tableViewSelectionDidChange(_ notification: Notification) {\n        updateVideoView()\n    }\n}\n"
  },
  {
    "path": "Resources/MainUI/VideosViewController.xib",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.Cocoa.XIB\" version=\"3.0\" toolsVersion=\"22154\" targetRuntime=\"MacOSX.Cocoa\" propertyAccessControl=\"none\" useAutolayout=\"YES\" customObjectInstantitationMethod=\"direct\">\n    <dependencies>\n        <deployment identifier=\"macosx\"/>\n        <plugIn identifier=\"com.apple.AVKitIBPlugin\" version=\"22154\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.CocoaPlugin\" version=\"22154\"/>\n        <capability name=\"Image references\" minToolsVersion=\"12.0\"/>\n        <capability name=\"System colors introduced in macOS 10.14\" minToolsVersion=\"10.0\"/>\n        <capability name=\"documents saved in the Xcode 8 format\" minToolsVersion=\"8.0\"/>\n    </dependencies>\n    <objects>\n        <customObject id=\"-2\" userLabel=\"File's Owner\" customClass=\"VideosViewController\" customModule=\"Aerial\" customModuleProvider=\"target\">\n            <connections>\n                <outlet property=\"downloadButton\" destination=\"qbz-9R-ZKI\" id=\"cpQ-6B-IRD\"/>\n                <outlet property=\"durationLabel\" destination=\"QbZ-qp-Ypz\" id=\"Dam-7i-ITB\"/>\n                <outlet property=\"formatLabel\" destination=\"lFd-fP-vmN\" id=\"Udo-ct-cYg\"/>\n                <outlet property=\"heroImageView\" destination=\"dtD-fV-1tE\" id=\"a1W-3I-cc9\"/>\n                <outlet property=\"heroPlayerView\" destination=\"U7m-tf-k3c\" id=\"vlt-8K-EGi\"/>\n                <outlet property=\"hideButton\" destination=\"dZn-gm-IU9\" id=\"y01-F6-ODn\"/>\n                <outlet property=\"isCachedImageView\" destination=\"EdU-Jl-WkG\" id=\"guj-Ae-dU8\"/>\n                <outlet property=\"locationLabel\" destination=\"dMl-IM-mBU\" id=\"KAk-Ul-NCl\"/>\n                <outlet property=\"playbackSpeedLabel\" destination=\"RDp-qo-Gd8\" id=\"xcM-Vi-4Bz\"/>\n                <outlet property=\"playbackSpeedSlider\" destination=\"6Ad-yU-hKx\" id=\"aBS-iQ-0Sx\"/>\n                <outlet property=\"rotationCacheNow\" destination=\"maH-hx-nRE\" id=\"AbZ-W8-RXU\"/>\n                <outlet property=\"rotationImage\" destination=\"Asf-6o-WdI\" id=\"tfa-oa-3jL\"/>\n                <outlet property=\"rotationPopup\" destination=\"zPp-ce-Ue7\" id=\"kgG-cM-Mdg\"/>\n                <outlet property=\"rotationSecondaryMenu\" destination=\"srx-t1-C7i\" id=\"Us8-xB-URN\"/>\n                <outlet property=\"rotationSecondaryPopup\" destination=\"pot-N7-9D4\" id=\"adk-k3-fPC\"/>\n                <outlet property=\"rotationView\" destination=\"ABO-qg-tKy\" id=\"Nbk-Yy-1wg\"/>\n                <outlet property=\"sceneTypeImageView\" destination=\"LOU-p1-jXB\" id=\"Q2c-Dd-3mO\"/>\n                <outlet property=\"showButton\" destination=\"Uwv-U2-C85\" id=\"4GT-N8-7id\"/>\n                <outlet property=\"sourceLabel\" destination=\"A1l-aS-ndR\" id=\"5bg-CG-JnQ\"/>\n                <outlet property=\"timeImageView\" destination=\"Y3a-EY-5S3\" id=\"uPd-b3-Xti\"/>\n                <outlet property=\"titleLabel\" destination=\"ewl-dK-yIY\" id=\"27E-tx-Zie\"/>\n                <outlet property=\"vibrancyLabel\" destination=\"Ikp-a0-d9g\" id=\"dFS-ld-lEV\"/>\n                <outlet property=\"vibrancySlider\" destination=\"9Um-fB-kbb\" id=\"WTH-86-IVF\"/>\n                <outlet property=\"videoListRuntimeLabel\" destination=\"BhB-s9-Rxu\" id=\"pjq-ZN-m24\"/>\n                <outlet property=\"videoListTableView\" destination=\"ezT-3u-Nqh\" id=\"eML-TR-SW0\"/>\n                <outlet property=\"view\" destination=\"Hz6-mo-xeY\" id=\"0bl-1N-x8E\"/>\n            </connections>\n        </customObject>\n        <customObject id=\"-1\" userLabel=\"First Responder\" customClass=\"FirstResponder\"/>\n        <customObject id=\"-3\" userLabel=\"Application\" customClass=\"NSObject\"/>\n        <customView translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Hz6-mo-xeY\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"809\" height=\"556\"/>\n            <subviews>\n                <stackView distribution=\"fill\" orientation=\"vertical\" alignment=\"leading\" spacing=\"0.0\" horizontalStackHuggingPriority=\"249.99998474121094\" verticalStackHuggingPriority=\"249.99998474121094\" detachesHiddenViews=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"4AO-lJ-AL6\">\n                    <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"809\" height=\"556\"/>\n                    <subviews>\n                        <customView verticalCompressionResistancePriority=\"680\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"ABO-qg-tKy\">\n                            <rect key=\"frame\" x=\"0.0\" y=\"504\" width=\"809\" height=\"52\"/>\n                            <subviews>\n                                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"k3W-6B-7ra\">\n                                    <rect key=\"frame\" x=\"52\" y=\"19\" width=\"56\" height=\"17\"/>\n                                    <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" title=\"Browse:\" id=\"qwA-3F-bfS\">\n                                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    </textFieldCell>\n                                </textField>\n                                <popUpButton verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"zPp-ce-Ue7\">\n                                    <rect key=\"frame\" x=\"117\" y=\"6\" width=\"142\" height=\"40\"/>\n                                    <popUpButtonCell key=\"cell\" type=\"push\" title=\"Everything\" bezelStyle=\"rounded\" alignment=\"left\" controlSize=\"large\" lineBreakMode=\"truncatingTail\" state=\"on\" borderStyle=\"borderAndBezel\" imageScaling=\"proportionallyDown\" inset=\"2\" selectedItem=\"jkn-QZ-30T\" id=\"D8b-BN-FEa\">\n                                        <behavior key=\"behavior\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                        <menu key=\"menu\" id=\"nqE-Xg-5qQ\">\n                                            <items>\n                                                <menuItem title=\"Everything\" state=\"on\" image=\"film\" catalog=\"system\" id=\"jkn-QZ-30T\"/>\n                                                <menuItem title=\"Favorites\" image=\"star\" catalog=\"system\" id=\"3rE-n7-xns\"/>\n                                                <menuItem title=\"Location\" image=\"location\" catalog=\"system\" id=\"szP-wR-xq3\">\n                                                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                </menuItem>\n                                                <menuItem title=\"Time\" image=\"clock\" catalog=\"system\" id=\"zOw-PF-QUs\">\n                                                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                </menuItem>\n                                                <menuItem title=\"Scene\" image=\"leaf\" catalog=\"system\" id=\"Kkb-eP-rnA\">\n                                                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                </menuItem>\n                                                <menuItem title=\"Source\" image=\"video.badge.plus\" catalog=\"system\" id=\"QHb-P6-22r\">\n                                                    <attributedString key=\"attributedTitle\"/>\n                                                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                </menuItem>\n                                                <menuItem title=\"Hidden\" image=\"eye.slash\" catalog=\"system\" id=\"QOZ-LO-L8m\">\n                                                    <attributedString key=\"attributedTitle\"/>\n                                                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                </menuItem>\n                                                <menuItem title=\"Set\" image=\"book\" catalog=\"system\" hidden=\"YES\" id=\"GkJ-Xg-Qmh\">\n                                                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                </menuItem>\n                                            </items>\n                                        </menu>\n                                    </popUpButtonCell>\n                                    <connections>\n                                        <action selector=\"rotationPopupChange:\" target=\"-2\" id=\"1uw-wE-kPg\"/>\n                                    </connections>\n                                </popUpButton>\n                                <imageView horizontalHuggingPriority=\"25\" verticalHuggingPriority=\"25\" horizontalCompressionResistancePriority=\"75\" verticalCompressionResistancePriority=\"75\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Asf-6o-WdI\">\n                                    <rect key=\"frame\" x=\"16\" y=\"5.5\" width=\"28.5\" height=\"41\"/>\n                                    <constraints>\n                                        <constraint firstAttribute=\"width\" constant=\"28\" id=\"4XK-VT-sn4\"/>\n                                    </constraints>\n                                    <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" id=\"02X-YM-lFe\">\n                                        <imageReference key=\"image\" image=\"film\" catalog=\"system\" symbolScale=\"large\"/>\n                                    </imageCell>\n                                    <color key=\"contentTintColor\" name=\"controlAccentColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                </imageView>\n                                <popUpButton verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"pot-N7-9D4\">\n                                    <rect key=\"frame\" x=\"265\" y=\"6\" width=\"50\" height=\"40\"/>\n                                    <popUpButtonCell key=\"cell\" type=\"push\" bezelStyle=\"rounded\" alignment=\"left\" controlSize=\"large\" lineBreakMode=\"truncatingTail\" borderStyle=\"borderAndBezel\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"1Qe-dD-9QB\">\n                                        <behavior key=\"behavior\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                        <menu key=\"menu\" id=\"srx-t1-C7i\"/>\n                                    </popUpButtonCell>\n                                    <connections>\n                                        <action selector=\"rotationSecondaryPopupChange:\" target=\"-2\" id=\"kyV-fQ-507\"/>\n                                    </connections>\n                                </popUpButton>\n                                <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"maH-hx-nRE\">\n                                    <rect key=\"frame\" x=\"633\" y=\"6\" width=\"174\" height=\"40\"/>\n                                    <buttonCell key=\"cell\" type=\"push\" title=\"Download rotation\" bezelStyle=\"rounded\" image=\"arrow.down.circle\" imagePosition=\"leading\" alignment=\"center\" controlSize=\"large\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"QFI-4w-0fn\">\n                                        <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                                        <font key=\"font\" metaFont=\"system\" size=\"14\"/>\n                                    </buttonCell>\n                                    <connections>\n                                        <action selector=\"rotationCacheNowClick:\" target=\"-2\" id=\"LRC-FC-EOR\"/>\n                                    </connections>\n                                </button>\n                            </subviews>\n                            <constraints>\n                                <constraint firstAttribute=\"trailing\" secondItem=\"maH-hx-nRE\" secondAttribute=\"trailing\" constant=\"8\" id=\"0XE-mE-TAS\"/>\n                                <constraint firstItem=\"Asf-6o-WdI\" firstAttribute=\"top\" secondItem=\"ABO-qg-tKy\" secondAttribute=\"top\" constant=\"10\" id=\"0n3-H1-cuA\"/>\n                                <constraint firstAttribute=\"bottom\" secondItem=\"Asf-6o-WdI\" secondAttribute=\"bottom\" constant=\"10\" id=\"2sN-ga-tWN\"/>\n                                <constraint firstItem=\"maH-hx-nRE\" firstAttribute=\"firstBaseline\" secondItem=\"zPp-ce-Ue7\" secondAttribute=\"firstBaseline\" id=\"8CD-CB-lia\"/>\n                                <constraint firstItem=\"pot-N7-9D4\" firstAttribute=\"firstBaseline\" secondItem=\"zPp-ce-Ue7\" secondAttribute=\"firstBaseline\" id=\"Di7-3S-Xfk\"/>\n                                <constraint firstItem=\"zPp-ce-Ue7\" firstAttribute=\"leading\" secondItem=\"k3W-6B-7ra\" secondAttribute=\"trailing\" constant=\"16\" id=\"OW2-kF-Khu\"/>\n                                <constraint firstItem=\"k3W-6B-7ra\" firstAttribute=\"leading\" secondItem=\"ABO-qg-tKy\" secondAttribute=\"leading\" constant=\"54\" id=\"Or0-dC-MTu\"/>\n                                <constraint firstItem=\"zPp-ce-Ue7\" firstAttribute=\"top\" secondItem=\"ABO-qg-tKy\" secondAttribute=\"top\" constant=\"12\" id=\"QNf-TX-cz9\"/>\n                                <constraint firstItem=\"pot-N7-9D4\" firstAttribute=\"leading\" secondItem=\"zPp-ce-Ue7\" secondAttribute=\"trailing\" constant=\"16\" id=\"UsM-mn-8cu\"/>\n                                <constraint firstItem=\"zPp-ce-Ue7\" firstAttribute=\"firstBaseline\" secondItem=\"k3W-6B-7ra\" secondAttribute=\"firstBaseline\" id=\"ZRH-9O-uPg\"/>\n                                <constraint firstItem=\"Asf-6o-WdI\" firstAttribute=\"leading\" secondItem=\"ABO-qg-tKy\" secondAttribute=\"leading\" constant=\"16\" id=\"kyL-FZ-qwS\"/>\n                                <constraint firstAttribute=\"bottom\" secondItem=\"zPp-ce-Ue7\" secondAttribute=\"bottom\" constant=\"12\" id=\"rjQ-NE-uv6\"/>\n                            </constraints>\n                        </customView>\n                        <customView horizontalHuggingPriority=\"400\" verticalHuggingPriority=\"150\" horizontalCompressionResistancePriority=\"500\" verticalCompressionResistancePriority=\"10\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"QjZ-f3-qUT\">\n                            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"809\" height=\"504\"/>\n                            <subviews>\n                                <stackView distribution=\"fill\" orientation=\"vertical\" alignment=\"leading\" spacing=\"0.0\" horizontalStackHuggingPriority=\"249.99998474121094\" verticalStackHuggingPriority=\"249.99998474121094\" detachesHiddenViews=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"IIU-60-IbM\">\n                                    <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"160\" height=\"504\"/>\n                                    <subviews>\n                                        <scrollView horizontalHuggingPriority=\"150\" verticalHuggingPriority=\"150\" horizontalCompressionResistancePriority=\"500\" verticalCompressionResistancePriority=\"500\" autohidesScrollers=\"YES\" horizontalLineScroll=\"102\" horizontalPageScroll=\"10\" verticalLineScroll=\"102\" verticalPageScroll=\"10\" usesPredominantAxisScrolling=\"NO\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"yZl-7N-5v4\">\n                                            <rect key=\"frame\" x=\"0.0\" y=\"22\" width=\"160\" height=\"482\"/>\n                                            <clipView key=\"contentView\" id=\"mgh-W3-r2c\">\n                                                <rect key=\"frame\" x=\"1\" y=\"1\" width=\"158\" height=\"480\"/>\n                                                <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                                                <subviews>\n                                                    <tableView verticalHuggingPriority=\"750\" allowsExpansionToolTips=\"YES\" columnAutoresizingStyle=\"lastColumnOnly\" tableStyle=\"plain\" columnReordering=\"NO\" columnSelection=\"YES\" columnResizing=\"NO\" multipleSelection=\"NO\" autosaveColumns=\"NO\" rowHeight=\"100\" rowSizeStyle=\"automatic\" viewBased=\"YES\" id=\"ezT-3u-Nqh\">\n                                                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"158\" height=\"480\"/>\n                                                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                                                        <size key=\"intercellSpacing\" width=\"3\" height=\"2\"/>\n                                                        <color key=\"backgroundColor\" name=\"controlBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                        <color key=\"gridColor\" name=\"gridColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                        <tableColumns>\n                                                            <tableColumn width=\"154\" minWidth=\"40\" maxWidth=\"1000\" id=\"X9R-cn-dQj\">\n                                                                <tableHeaderCell key=\"headerCell\" lineBreakMode=\"truncatingTail\" borderStyle=\"border\">\n                                                                    <color key=\"textColor\" name=\"headerTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                                    <color key=\"backgroundColor\" name=\"headerColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                                </tableHeaderCell>\n                                                                <textFieldCell key=\"dataCell\" lineBreakMode=\"truncatingTail\" selectable=\"YES\" editable=\"YES\" title=\"Text Cell\" id=\"dh5-3q-Xg6\">\n                                                                    <font key=\"font\" metaFont=\"system\"/>\n                                                                    <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                                    <color key=\"backgroundColor\" name=\"controlBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                                </textFieldCell>\n                                                                <tableColumnResizingMask key=\"resizingMask\" resizeWithTable=\"YES\" userResizable=\"YES\"/>\n                                                                <prototypeCellViews>\n                                                                    <tableCellView identifier=\"ImageCellID\" id=\"iGt-T1-KlK\" customClass=\"VideoCellView\" customModule=\"Aerial\" customModuleProvider=\"target\">\n                                                                        <rect key=\"frame\" x=\"1\" y=\"1\" width=\"154\" height=\"100\"/>\n                                                                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                                                                        <subviews>\n                                                                            <imageView horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Hsn-bp-Gft\">\n                                                                                <rect key=\"frame\" x=\"1\" y=\"16\" width=\"144\" height=\"81\"/>\n                                                                                <autoresizingMask key=\"autoresizingMask\" flexibleMinY=\"YES\"/>\n                                                                                <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" id=\"Tt5-fI-GZN\"/>\n                                                                            </imageView>\n                                                                            <button toolTip=\"Favorite videos will not be removed from your cache\" verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"ZzB-8p-JVZ\">\n                                                                                <rect key=\"frame\" x=\"2\" y=\"15\" width=\"25\" height=\"30\"/>\n                                                                                <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                                                                                <buttonCell key=\"cell\" type=\"square\" bezelStyle=\"shadowlessSquare\" image=\"star\" imagePosition=\"only\" alternateImage=\"star.fill\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"oyr-84-Ais\">\n                                                                                    <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                                                                                    <font key=\"font\" metaFont=\"system\"/>\n                                                                                </buttonCell>\n                                                                            </button>\n                                                                            <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" id=\"HAC-xd-S3Q\">\n                                                                                <rect key=\"frame\" x=\"-1\" y=\"0.0\" width=\"150\" height=\"14\"/>\n                                                                                <autoresizingMask key=\"autoresizingMask\" flexibleMinY=\"YES\"/>\n                                                                                <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" alignment=\"center\" title=\"Label\" id=\"khV-1P-4zT\">\n                                                                                    <font key=\"font\" metaFont=\"smallSystem\"/>\n                                                                                    <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                                                    <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                                                </textFieldCell>\n                                                                            </textField>\n                                                                            <button fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"hry-7E-lTN\">\n                                                                                <rect key=\"frame\" x=\"121\" y=\"17\" width=\"25\" height=\"25\"/>\n                                                                                <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                                                                                <buttonCell key=\"cell\" type=\"square\" bezelStyle=\"shadowlessSquare\" image=\"arrow.down.circle.fill\" imagePosition=\"only\" alignment=\"center\" imageScaling=\"proportionallyUpOrDown\" inset=\"2\" id=\"Qim-uy-I2M\">\n                                                                                    <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                                                                                    <font key=\"font\" metaFont=\"system\"/>\n                                                                                </buttonCell>\n                                                                                <color key=\"contentTintColor\" white=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"genericGamma22GrayColorSpace\"/>\n                                                                                <connections>\n                                                                                    <action selector=\"downloadButtonClick:\" target=\"iGt-T1-KlK\" id=\"kGg-5H-yN1\"/>\n                                                                                </connections>\n                                                                            </button>\n                                                                        </subviews>\n                                                                        <connections>\n                                                                            <outlet property=\"checkButton\" destination=\"ZzB-8p-JVZ\" id=\"MSK-Qb-Wxs\"/>\n                                                                            <outlet property=\"downloadButton\" destination=\"hry-7E-lTN\" id=\"VNd-vt-jid\"/>\n                                                                            <outlet property=\"label\" destination=\"HAC-xd-S3Q\" id=\"noh-pf-2li\"/>\n                                                                            <outlet property=\"thumbView\" destination=\"Hsn-bp-Gft\" id=\"wnu-qH-xdt\"/>\n                                                                        </connections>\n                                                                    </tableCellView>\n                                                                </prototypeCellViews>\n                                                            </tableColumn>\n                                                        </tableColumns>\n                                                    </tableView>\n                                                </subviews>\n                                            </clipView>\n                                            <scroller key=\"horizontalScroller\" hidden=\"YES\" wantsLayer=\"YES\" verticalHuggingPriority=\"750\" horizontal=\"YES\" id=\"jyP-JY-xNc\">\n                                                <rect key=\"frame\" x=\"1\" y=\"490\" width=\"158\" height=\"16\"/>\n                                                <autoresizingMask key=\"autoresizingMask\"/>\n                                            </scroller>\n                                            <scroller key=\"verticalScroller\" hidden=\"YES\" wantsLayer=\"YES\" verticalHuggingPriority=\"750\" horizontal=\"NO\" id=\"PR2-S3-3ig\">\n                                                <rect key=\"frame\" x=\"224\" y=\"17\" width=\"15\" height=\"102\"/>\n                                                <autoresizingMask key=\"autoresizingMask\"/>\n                                            </scroller>\n                                        </scrollView>\n                                        <customView horizontalCompressionResistancePriority=\"50\" verticalCompressionResistancePriority=\"50\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"mih-eT-KCK\">\n                                            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"160\" height=\"22\"/>\n                                            <subviews>\n                                                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"BhB-s9-Rxu\">\n                                                    <rect key=\"frame\" x=\"21\" y=\"4\" width=\"118\" height=\"14\"/>\n                                                    <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" alignment=\"center\" title=\"8 videos, 38 minutes\" id=\"sHq-Nl-qgc\">\n                                                        <font key=\"font\" metaFont=\"smallSystem\"/>\n                                                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                    </textFieldCell>\n                                                </textField>\n                                            </subviews>\n                                            <constraints>\n                                                <constraint firstItem=\"BhB-s9-Rxu\" firstAttribute=\"centerX\" secondItem=\"mih-eT-KCK\" secondAttribute=\"centerX\" id=\"M0s-50-VI2\"/>\n                                                <constraint firstAttribute=\"bottom\" secondItem=\"BhB-s9-Rxu\" secondAttribute=\"bottom\" constant=\"4\" id=\"WbB-u2-UyF\"/>\n                                                <constraint firstItem=\"BhB-s9-Rxu\" firstAttribute=\"top\" secondItem=\"mih-eT-KCK\" secondAttribute=\"top\" constant=\"4\" id=\"uTd-cK-5NC\"/>\n                                            </constraints>\n                                        </customView>\n                                    </subviews>\n                                    <constraints>\n                                        <constraint firstAttribute=\"width\" constant=\"160\" id=\"Oeg-h0-oSG\"/>\n                                    </constraints>\n                                    <visibilityPriorities>\n                                        <integer value=\"1000\"/>\n                                        <integer value=\"1000\"/>\n                                    </visibilityPriorities>\n                                    <customSpacing>\n                                        <real value=\"3.4028234663852886e+38\"/>\n                                        <real value=\"3.4028234663852886e+38\"/>\n                                    </customSpacing>\n                                </stackView>\n                                <customView horizontalCompressionResistancePriority=\"1000\" verticalCompressionResistancePriority=\"1000\" id=\"FJa-0G-94n\">\n                                    <rect key=\"frame\" x=\"160\" y=\"0.0\" width=\"649\" height=\"504\"/>\n                                    <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                                    <subviews>\n                                        <avPlayerView horizontalHuggingPriority=\"300\" verticalHuggingPriority=\"300\" horizontalCompressionResistancePriority=\"300\" verticalCompressionResistancePriority=\"300\" controlsStyle=\"inline\" id=\"U7m-tf-k3c\">\n                                            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"649\" height=\"504\"/>\n                                            <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                                        </avPlayerView>\n                                        <imageView horizontalHuggingPriority=\"300\" verticalHuggingPriority=\"10\" horizontalCompressionResistancePriority=\"300\" verticalCompressionResistancePriority=\"10\" id=\"dtD-fV-1tE\" customClass=\"AspectFillNSImageView\" customModule=\"Aerial\" customModuleProvider=\"target\">\n                                            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"649\" height=\"504\"/>\n                                            <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                                            <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"axesIndependently\" id=\"ajB-qa-0uN\"/>\n                                        </imageView>\n                                        <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"ewl-dK-yIY\">\n                                            <rect key=\"frame\" x=\"18\" y=\"451\" width=\"76\" height=\"33\"/>\n                                            <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"Label\" id=\"a8N-Pb-JjJ\">\n                                                <font key=\"font\" metaFont=\"systemBold\" size=\"28\"/>\n                                                <color key=\"textColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"0.84705882352941175\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                                <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                            </textFieldCell>\n                                        </textField>\n                                        <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"dMl-IM-mBU\">\n                                            <rect key=\"frame\" x=\"18\" y=\"413\" width=\"69\" height=\"30\"/>\n                                            <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"Label\" id=\"fCH-hA-WF6\">\n                                                <font key=\"font\" metaFont=\"systemSemibold\" size=\"26\"/>\n                                                <color key=\"textColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"0.84705882349999995\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                                <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                            </textFieldCell>\n                                        </textField>\n                                        <imageView horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Y3a-EY-5S3\">\n                                            <rect key=\"frame\" x=\"525\" y=\"436\" width=\"48\" height=\"48\"/>\n                                            <constraints>\n                                                <constraint firstAttribute=\"height\" constant=\"48\" id=\"hFQ-xZ-hrP\"/>\n                                                <constraint firstAttribute=\"width\" constant=\"48\" id=\"vaE-ul-NoE\"/>\n                                            </constraints>\n                                            <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" image=\"sun.max\" id=\"yao-GT-GTV\"/>\n                                        </imageView>\n                                        <imageView horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"LOU-p1-jXB\">\n                                            <rect key=\"frame\" x=\"581\" y=\"433.5\" width=\"48.5\" height=\"53\"/>\n                                            <constraints>\n                                                <constraint firstAttribute=\"width\" constant=\"48\" id=\"bGx-5j-jPU\"/>\n                                                <constraint firstAttribute=\"height\" constant=\"48\" id=\"vfA-jx-AEO\"/>\n                                            </constraints>\n                                            <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyUpOrDown\" image=\"leaf\" catalog=\"system\" id=\"yB7-no-i7J\"/>\n                                            <color key=\"contentTintColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"0.84705882349999995\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                        </imageView>\n                                        <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"lFd-fP-vmN\">\n                                            <rect key=\"frame\" x=\"88\" y=\"385\" width=\"60\" height=\"20\"/>\n                                            <textFieldCell key=\"cell\" controlSize=\"small\" lineBreakMode=\"clipping\" borderStyle=\"border\" alignment=\"center\" title=\"4K HDR\" drawsBackground=\"YES\" id=\"mrA-db-ixg\" customClass=\"VerticallyAlignedTextFieldCell\" customModule=\"Aerial\" customModuleProvider=\"target\">\n                                                <font key=\"font\" metaFont=\"system\"/>\n                                                <color key=\"textColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"0.84705882349999995\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                                <color key=\"backgroundColor\" red=\"0.0\" green=\"0.0\" blue=\"0.0\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                            </textFieldCell>\n                                        </textField>\n                                        <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"A1l-aS-ndR\">\n                                            <rect key=\"frame\" x=\"20\" y=\"385\" width=\"60\" height=\"20\"/>\n                                            <textFieldCell key=\"cell\" controlSize=\"small\" lineBreakMode=\"clipping\" borderStyle=\"border\" alignment=\"center\" title=\"tvOS 13\" drawsBackground=\"YES\" id=\"p1a-Y2-HhA\" customClass=\"VerticallyAlignedTextFieldCell\" customModule=\"Aerial\" customModuleProvider=\"target\">\n                                                <font key=\"font\" metaFont=\"system\"/>\n                                                <color key=\"textColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"0.84705882349999995\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                                <color key=\"backgroundColor\" red=\"0.0\" green=\"0.0\" blue=\"0.0\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                            </textFieldCell>\n                                        </textField>\n                                        <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"QbZ-qp-Ypz\">\n                                            <rect key=\"frame\" x=\"18\" y=\"20\" width=\"106\" height=\"19\"/>\n                                            <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"Duration: 3:04\" id=\"bYd-xh-PcR\">\n                                                <font key=\"font\" metaFont=\"systemMedium\" size=\"15\"/>\n                                                <color key=\"textColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"0.84705882349999995\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                                <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                            </textFieldCell>\n                                        </textField>\n                                        <button hidden=\"YES\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"y5S-IQ-OiH\">\n                                            <rect key=\"frame\" x=\"471\" y=\"436\" width=\"48\" height=\"48\"/>\n                                            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                                            <buttonCell key=\"cell\" type=\"square\" bezelStyle=\"shadowlessSquare\" image=\"star.fill\" imagePosition=\"only\" alignment=\"center\" alternateImage=\"star\" state=\"on\" imageScaling=\"proportionallyUpOrDown\" inset=\"2\" id=\"h0R-is-uW4\">\n                                                <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                                                <font key=\"font\" metaFont=\"system\"/>\n                                            </buttonCell>\n                                        </button>\n                                        <stackView distribution=\"fill\" orientation=\"vertical\" alignment=\"leading\" horizontalStackHuggingPriority=\"249.99998474121094\" verticalStackHuggingPriority=\"249.99998474121094\" detachesHiddenViews=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"95z-4q-gHF\">\n                                            <rect key=\"frame\" x=\"503\" y=\"320\" width=\"126\" height=\"100\"/>\n                                            <subviews>\n                                                <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"qbz-9R-ZKI\">\n                                                    <rect key=\"frame\" x=\"-6\" y=\"66\" width=\"138\" height=\"40\"/>\n                                                    <buttonCell key=\"cell\" type=\"push\" title=\"Download now\" bezelStyle=\"rounded\" image=\"NSTouchBarDownloadTemplate\" imagePosition=\"leading\" alignment=\"center\" controlSize=\"large\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"jHr-z3-qDy\">\n                                                        <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                                                        <font key=\"font\" metaFont=\"system\"/>\n                                                    </buttonCell>\n                                                    <connections>\n                                                        <action selector=\"downloadButton:\" target=\"-2\" id=\"vpM-d2-siO\"/>\n                                                    </connections>\n                                                </button>\n                                                <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"dZn-gm-IU9\">\n                                                    <rect key=\"frame\" x=\"-6\" y=\"30\" width=\"138\" height=\"40\"/>\n                                                    <buttonCell key=\"cell\" type=\"push\" title=\"Hide\" bezelStyle=\"rounded\" image=\"eye.slash\" catalog=\"system\" imagePosition=\"leading\" alignment=\"center\" controlSize=\"large\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"EPG-QN-CFH\">\n                                                        <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                                                        <font key=\"font\" metaFont=\"system\"/>\n                                                    </buttonCell>\n                                                    <connections>\n                                                        <action selector=\"hideButtonClick:\" target=\"-2\" id=\"W03-ou-vXx\"/>\n                                                    </connections>\n                                                </button>\n                                                <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Uwv-U2-C85\">\n                                                    <rect key=\"frame\" x=\"-6\" y=\"-6\" width=\"138\" height=\"40\"/>\n                                                    <buttonCell key=\"cell\" type=\"push\" title=\"Show\" bezelStyle=\"rounded\" image=\"eye\" catalog=\"system\" imagePosition=\"left\" alignment=\"center\" controlSize=\"large\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"Q7h-xo-ddL\">\n                                                        <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                                                        <font key=\"font\" metaFont=\"system\"/>\n                                                    </buttonCell>\n                                                    <connections>\n                                                        <action selector=\"showButtonClick:\" target=\"-2\" id=\"XMf-Ef-rNn\"/>\n                                                    </connections>\n                                                </button>\n                                            </subviews>\n                                            <constraints>\n                                                <constraint firstItem=\"Uwv-U2-C85\" firstAttribute=\"trailing\" secondItem=\"qbz-9R-ZKI\" secondAttribute=\"trailing\" id=\"VVU-dN-0DH\"/>\n                                                <constraint firstItem=\"dZn-gm-IU9\" firstAttribute=\"trailing\" secondItem=\"qbz-9R-ZKI\" secondAttribute=\"trailing\" id=\"liS-E2-Sbb\"/>\n                                            </constraints>\n                                            <visibilityPriorities>\n                                                <integer value=\"1000\"/>\n                                                <integer value=\"1000\"/>\n                                                <integer value=\"1000\"/>\n                                            </visibilityPriorities>\n                                            <customSpacing>\n                                                <real value=\"3.4028234663852886e+38\"/>\n                                                <real value=\"3.4028234663852886e+38\"/>\n                                                <real value=\"3.4028234663852886e+38\"/>\n                                            </customSpacing>\n                                        </stackView>\n                                        <slider verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"9Um-fB-kbb\">\n                                            <rect key=\"frame\" x=\"462\" y=\"48\" width=\"169\" height=\"28\"/>\n                                            <constraints>\n                                                <constraint firstAttribute=\"height\" constant=\"20\" id=\"qUr-7F-H1p\"/>\n                                                <constraint firstAttribute=\"width\" constant=\"165\" id=\"qxv-ww-jI5\"/>\n                                            </constraints>\n                                            <sliderCell key=\"cell\" controlSize=\"large\" continuous=\"YES\" state=\"on\" alignment=\"left\" minValue=\"-1\" maxValue=\"1\" tickMarkPosition=\"above\" numberOfTickMarks=\"3\" sliderType=\"linear\" id=\"mfW-mT-Kre\"/>\n                                            <connections>\n                                                <action selector=\"vibrancySliderChange:\" target=\"-2\" id=\"oqY-zh-99e\"/>\n                                            </connections>\n                                        </slider>\n                                        <slider verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"6Ad-yU-hKx\">\n                                            <rect key=\"frame\" x=\"462\" y=\"14\" width=\"169\" height=\"28\"/>\n                                            <constraints>\n                                                <constraint firstAttribute=\"width\" constant=\"165\" id=\"KxC-0m-cdh\"/>\n                                                <constraint firstAttribute=\"height\" constant=\"20\" id=\"ZSI-B7-UTY\"/>\n                                            </constraints>\n                                            <sliderCell key=\"cell\" controlSize=\"large\" continuous=\"YES\" state=\"on\" alignment=\"left\" maxValue=\"2\" doubleValue=\"1\" tickMarkPosition=\"above\" numberOfTickMarks=\"9\" sliderType=\"linear\" id=\"jOW-8v-JGB\"/>\n                                            <connections>\n                                                <action selector=\"playbackSpeedSliderChange:\" target=\"-2\" id=\"m74-DD-1Eq\"/>\n                                            </connections>\n                                        </slider>\n                                        <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Ikp-a0-d9g\">\n                                            <rect key=\"frame\" x=\"378\" y=\"55\" width=\"72\" height=\"19\"/>\n                                            <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" alignment=\"right\" title=\"Vibrance:\" id=\"VSx-3A-4eo\">\n                                                <font key=\"font\" metaFont=\"systemMedium\" size=\"15\"/>\n                                                <color key=\"textColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"0.84705882349999995\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                                <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                            </textFieldCell>\n                                        </textField>\n                                        <imageView toolTip=\"Video is in cache\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"EdU-Jl-WkG\">\n                                            <rect key=\"frame\" x=\"152\" y=\"381\" width=\"22\" height=\"26\"/>\n                                            <constraints>\n                                                <constraint firstAttribute=\"width\" constant=\"22\" id=\"Izn-e7-R3T\"/>\n                                                <constraint firstAttribute=\"height\" constant=\"22\" id=\"OGP-4R-fSd\"/>\n                                            </constraints>\n                                            <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" image=\"internaldrive\" catalog=\"system\" id=\"eJT-Xr-JIs\"/>\n                                            <color key=\"contentTintColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"0.84705882349999995\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                        </imageView>\n                                        <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"RDp-qo-Gd8\">\n                                            <rect key=\"frame\" x=\"329\" y=\"20\" width=\"121\" height=\"19\"/>\n                                            <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" alignment=\"right\" title=\"Playback Speed:\" id=\"0lg-BB-dYc\">\n                                                <font key=\"font\" metaFont=\"systemMedium\" size=\"15\"/>\n                                                <color key=\"textColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"0.84705882349999995\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                                                <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                            </textFieldCell>\n                                        </textField>\n                                    </subviews>\n                                    <constraints>\n                                        <constraint firstItem=\"QbZ-qp-Ypz\" firstAttribute=\"leading\" secondItem=\"FJa-0G-94n\" secondAttribute=\"leading\" priority=\"100\" constant=\"20\" id=\"08s-nn-r71\"/>\n                                        <constraint firstItem=\"QbZ-qp-Ypz\" firstAttribute=\"leading\" secondItem=\"ewl-dK-yIY\" secondAttribute=\"leading\" id=\"0aW-N9-7XK\"/>\n                                        <constraint firstAttribute=\"trailing\" secondItem=\"6Ad-yU-hKx\" secondAttribute=\"trailing\" priority=\"100\" constant=\"20\" symbolic=\"YES\" id=\"5fj-Px-9X5\"/>\n                                        <constraint firstItem=\"Y3a-EY-5S3\" firstAttribute=\"top\" secondItem=\"FJa-0G-94n\" secondAttribute=\"top\" constant=\"20\" symbolic=\"YES\" id=\"Agw-zF-nfa\"/>\n                                        <constraint firstItem=\"A1l-aS-ndR\" firstAttribute=\"top\" secondItem=\"dMl-IM-mBU\" secondAttribute=\"bottom\" constant=\"8\" symbolic=\"YES\" id=\"BvK-8W-P2S\"/>\n                                        <constraint firstItem=\"dMl-IM-mBU\" firstAttribute=\"leading\" secondItem=\"ewl-dK-yIY\" secondAttribute=\"leading\" id=\"DJg-ke-ta0\"/>\n                                        <constraint firstItem=\"EdU-Jl-WkG\" firstAttribute=\"leading\" secondItem=\"lFd-fP-vmN\" secondAttribute=\"trailing\" constant=\"4\" id=\"DfP-zH-5yp\"/>\n                                        <constraint firstItem=\"dMl-IM-mBU\" firstAttribute=\"top\" secondItem=\"ewl-dK-yIY\" secondAttribute=\"bottom\" constant=\"8\" symbolic=\"YES\" id=\"Dze-AI-cnq\"/>\n                                        <constraint firstItem=\"EdU-Jl-WkG\" firstAttribute=\"top\" secondItem=\"lFd-fP-vmN\" secondAttribute=\"top\" id=\"HMw-10-Joy\"/>\n                                        <constraint firstAttribute=\"bottom\" secondItem=\"6Ad-yU-hKx\" secondAttribute=\"bottom\" constant=\"20\" symbolic=\"YES\" id=\"HOm-Y5-UjM\"/>\n                                        <constraint firstItem=\"LOU-p1-jXB\" firstAttribute=\"leading\" secondItem=\"Y3a-EY-5S3\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"L63-x4-B2U\"/>\n                                        <constraint firstItem=\"9Um-fB-kbb\" firstAttribute=\"leading\" secondItem=\"Ikp-a0-d9g\" secondAttribute=\"trailing\" constant=\"16\" id=\"Lxq-tu-gDS\"/>\n                                        <constraint firstItem=\"6Ad-yU-hKx\" firstAttribute=\"top\" secondItem=\"9Um-fB-kbb\" secondAttribute=\"bottom\" constant=\"14\" id=\"Qen-OT-MpJ\"/>\n                                        <constraint firstItem=\"LOU-p1-jXB\" firstAttribute=\"top\" secondItem=\"FJa-0G-94n\" secondAttribute=\"top\" constant=\"20\" symbolic=\"YES\" id=\"RCb-cg-dTt\"/>\n                                        <constraint firstItem=\"A1l-aS-ndR\" firstAttribute=\"leading\" secondItem=\"ewl-dK-yIY\" secondAttribute=\"leading\" id=\"WIn-8v-0HC\"/>\n                                        <constraint firstItem=\"6Ad-yU-hKx\" firstAttribute=\"trailing\" secondItem=\"9Um-fB-kbb\" secondAttribute=\"trailing\" id=\"ZDJ-c2-jTQ\"/>\n                                        <constraint firstItem=\"lFd-fP-vmN\" firstAttribute=\"leading\" secondItem=\"A1l-aS-ndR\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"dh8-3c-vh9\"/>\n                                        <constraint firstAttribute=\"trailing\" secondItem=\"95z-4q-gHF\" secondAttribute=\"trailing\" constant=\"20\" symbolic=\"YES\" id=\"fr5-nI-WRm\"/>\n                                        <constraint firstItem=\"RDp-qo-Gd8\" firstAttribute=\"firstBaseline\" secondItem=\"QbZ-qp-Ypz\" secondAttribute=\"firstBaseline\" id=\"g0Z-yU-5Jq\"/>\n                                        <constraint firstItem=\"RDp-qo-Gd8\" firstAttribute=\"top\" secondItem=\"Ikp-a0-d9g\" secondAttribute=\"bottom\" constant=\"16\" id=\"ggv-tH-XVs\"/>\n                                        <constraint firstItem=\"ewl-dK-yIY\" firstAttribute=\"top\" secondItem=\"FJa-0G-94n\" secondAttribute=\"top\" constant=\"20\" symbolic=\"YES\" id=\"i2b-DX-ULE\"/>\n                                        <constraint firstItem=\"6Ad-yU-hKx\" firstAttribute=\"leading\" secondItem=\"RDp-qo-Gd8\" secondAttribute=\"trailing\" constant=\"16\" id=\"nIL-vK-isg\"/>\n                                        <constraint firstAttribute=\"trailing\" secondItem=\"LOU-p1-jXB\" secondAttribute=\"trailing\" priority=\"100\" constant=\"20\" symbolic=\"YES\" id=\"nmx-aE-7RB\"/>\n                                        <constraint firstItem=\"95z-4q-gHF\" firstAttribute=\"top\" secondItem=\"Y3a-EY-5S3\" secondAttribute=\"bottom\" constant=\"16\" id=\"qZ6-ge-ugK\"/>\n                                        <constraint firstAttribute=\"bottom\" secondItem=\"QbZ-qp-Ypz\" secondAttribute=\"bottom\" constant=\"20\" id=\"vxb-jb-kGM\"/>\n                                        <constraint firstItem=\"lFd-fP-vmN\" firstAttribute=\"firstBaseline\" secondItem=\"A1l-aS-ndR\" secondAttribute=\"firstBaseline\" id=\"yHJ-dL-aFu\"/>\n                                    </constraints>\n                                </customView>\n                            </subviews>\n                            <constraints>\n                                <constraint firstAttribute=\"bottom\" secondItem=\"IIU-60-IbM\" secondAttribute=\"bottom\" id=\"5b2-E3-DvR\"/>\n                                <constraint firstItem=\"IIU-60-IbM\" firstAttribute=\"top\" secondItem=\"QjZ-f3-qUT\" secondAttribute=\"top\" id=\"6tV-0m-gQQ\"/>\n                                <constraint firstItem=\"IIU-60-IbM\" firstAttribute=\"leading\" secondItem=\"QjZ-f3-qUT\" secondAttribute=\"leading\" id=\"ZoJ-xW-fHy\"/>\n                                <constraint firstItem=\"FJa-0G-94n\" firstAttribute=\"leading\" secondItem=\"IIU-60-IbM\" secondAttribute=\"trailing\" id=\"hF8-ee-mTF\"/>\n                            </constraints>\n                        </customView>\n                    </subviews>\n                    <constraints>\n                        <constraint firstItem=\"ABO-qg-tKy\" firstAttribute=\"top\" secondItem=\"4AO-lJ-AL6\" secondAttribute=\"top\" id=\"Uqq-n8-040\"/>\n                        <constraint firstItem=\"ABO-qg-tKy\" firstAttribute=\"leading\" secondItem=\"4AO-lJ-AL6\" secondAttribute=\"leading\" id=\"dre-ux-gRP\"/>\n                        <constraint firstAttribute=\"trailing\" secondItem=\"ABO-qg-tKy\" secondAttribute=\"trailing\" id=\"edk-xM-XBe\"/>\n                        <constraint firstAttribute=\"trailing\" secondItem=\"QjZ-f3-qUT\" secondAttribute=\"trailing\" id=\"iMj-C5-pew\"/>\n                    </constraints>\n                    <visibilityPriorities>\n                        <integer value=\"1000\"/>\n                        <integer value=\"1000\"/>\n                    </visibilityPriorities>\n                    <customSpacing>\n                        <real value=\"3.4028234663852886e+38\"/>\n                        <real value=\"3.4028234663852886e+38\"/>\n                    </customSpacing>\n                </stackView>\n            </subviews>\n            <constraints>\n                <constraint firstAttribute=\"height\" relation=\"greaterThanOrEqual\" constant=\"530\" id=\"0ot-qb-hxA\"/>\n                <constraint firstAttribute=\"bottom\" secondItem=\"4AO-lJ-AL6\" secondAttribute=\"bottom\" id=\"1MW-kc-Te1\"/>\n                <constraint firstItem=\"4AO-lJ-AL6\" firstAttribute=\"leading\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"leading\" id=\"3T8-Jm-lP8\"/>\n                <constraint firstAttribute=\"trailing\" secondItem=\"4AO-lJ-AL6\" secondAttribute=\"trailing\" id=\"D9m-AS-QkC\"/>\n                <constraint firstItem=\"4AO-lJ-AL6\" firstAttribute=\"top\" secondItem=\"Hz6-mo-xeY\" secondAttribute=\"top\" id=\"fbT-MS-TrY\"/>\n                <constraint firstAttribute=\"width\" relation=\"greaterThanOrEqual\" constant=\"809\" id=\"k5z-6W-Eoq\"/>\n            </constraints>\n            <point key=\"canvasLocation\" x=\"227.5\" y=\"-28.5\"/>\n        </customView>\n        <customView id=\"YSa-aK-yLJ\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"797\" height=\"512\"/>\n            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n            <subviews>\n                <box fixedFrame=\"YES\" boxType=\"custom\" cornerRadius=\"4\" title=\"Box\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"M1m-uf-hdC\">\n                    <rect key=\"frame\" x=\"-8\" y=\"0.0\" width=\"805\" height=\"520\"/>\n                    <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                    <view key=\"contentView\" id=\"EyY-Cn-x4h\">\n                        <rect key=\"frame\" x=\"1\" y=\"1\" width=\"803\" height=\"518\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                    </view>\n                    <color key=\"borderColor\" white=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"genericGamma22GrayColorSpace\"/>\n                    <color key=\"fillColor\" white=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"genericGamma22GrayColorSpace\"/>\n                </box>\n                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" ambiguous=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"R5E-Ac-s6u\">\n                    <rect key=\"frame\" x=\"50\" y=\"471\" width=\"135\" height=\"16\"/>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" title=\"Aerial currently plays:\" id=\"UTs-Mx-NIw\">\n                        <font key=\"font\" metaFont=\"system\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <popUpButton verticalHuggingPriority=\"750\" ambiguous=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"zyI-GA-Pn4\">\n                    <rect key=\"frame\" x=\"188\" y=\"458\" width=\"156\" height=\"40\"/>\n                    <popUpButtonCell key=\"cell\" type=\"push\" title=\"Locations\" bezelStyle=\"rounded\" alignment=\"left\" controlSize=\"large\" lineBreakMode=\"truncatingTail\" state=\"on\" borderStyle=\"borderAndBezel\" imageScaling=\"proportionallyDown\" inset=\"2\" selectedItem=\"aAq-NZ-YB8\" id=\"QWj-F0-Vs1\">\n                        <behavior key=\"behavior\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" metaFont=\"menu\"/>\n                        <menu key=\"menu\" id=\"J60-Ou-gg6\">\n                            <items>\n                                <menuItem title=\"Everything\" image=\"film\" catalog=\"system\" id=\"hg4-C7-oRd\"/>\n                                <menuItem title=\"Only Favorites\" image=\"star\" catalog=\"system\" id=\"fU6-VX-I8K\"/>\n                                <menuItem title=\"Locations\" state=\"on\" image=\"location\" catalog=\"system\" id=\"aAq-NZ-YB8\">\n                                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                </menuItem>\n                                <menuItem title=\"Time\" image=\"clock\" catalog=\"system\" id=\"ezP-iS-NdD\">\n                                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                </menuItem>\n                                <menuItem title=\"Scene\" image=\"leaf\" catalog=\"system\" id=\"GdB-Jo-fzo\">\n                                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                </menuItem>\n                                <menuItem title=\"Source\" image=\"video.badge.plus\" catalog=\"system\" id=\"kOV-BE-v90\">\n                                    <attributedString key=\"attributedTitle\"/>\n                                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                </menuItem>\n                                <menuItem title=\"Set\" image=\"book\" catalog=\"system\" hidden=\"YES\" id=\"qt8-DA-caM\">\n                                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                </menuItem>\n                            </items>\n                        </menu>\n                    </popUpButtonCell>\n                    <connections>\n                        <action selector=\"rotationPopupChange:\" target=\"-2\" id=\"cj1-Qt-RYx\"/>\n                    </connections>\n                </popUpButton>\n                <imageView horizontalHuggingPriority=\"25\" verticalHuggingPriority=\"25\" horizontalCompressionResistancePriority=\"75\" verticalCompressionResistancePriority=\"75\" ambiguous=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"r3Q-f4-uvO\">\n                    <rect key=\"frame\" x=\"20\" y=\"464\" width=\"24.5\" height=\"28\"/>\n                    <constraints>\n                        <constraint firstAttribute=\"width\" constant=\"24\" id=\"5i5-sS-s5M\"/>\n                    </constraints>\n                    <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" image=\"play\" catalog=\"system\" id=\"mkh-NM-Bfm\"/>\n                    <color key=\"contentTintColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                </imageView>\n                <imageView horizontalHuggingPriority=\"25\" verticalHuggingPriority=\"25\" horizontalCompressionResistancePriority=\"75\" verticalCompressionResistancePriority=\"75\" ambiguous=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"ZNR-mk-thR\">\n                    <rect key=\"frame\" x=\"20\" y=\"217\" width=\"24\" height=\"28\"/>\n                    <constraints>\n                        <constraint firstAttribute=\"width\" constant=\"24\" id=\"iYZ-Sn-ou4\"/>\n                    </constraints>\n                    <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" image=\"externaldrive\" catalog=\"system\" id=\"a7l-Sp-Ceh\"/>\n                    <color key=\"contentTintColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                </imageView>\n                <imageView horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"k84-KG-OF6\">\n                    <rect key=\"frame\" x=\"32\" y=\"366\" width=\"157\" height=\"86\"/>\n                    <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                    <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" image=\"screen0\" id=\"Ss6-MV-FWM\"/>\n                </imageView>\n                <button verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"gDs-uI-9B0\">\n                    <rect key=\"frame\" x=\"37\" y=\"373\" width=\"22\" height=\"22\"/>\n                    <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                    <buttonCell key=\"cell\" type=\"check\" bezelStyle=\"regularSquare\" imagePosition=\"left\" controlSize=\"large\" state=\"on\" inset=\"2\" id=\"pmo-ty-HoX\">\n                        <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\"/>\n                    </buttonCell>\n                </button>\n                <imageView horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"kZ8-Ge-3gE\">\n                    <rect key=\"frame\" x=\"205\" y=\"366\" width=\"157\" height=\"86\"/>\n                    <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                    <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" image=\"screen0\" id=\"GVc-6h-d3W\"/>\n                </imageView>\n                <button verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"OpG-Of-llp\">\n                    <rect key=\"frame\" x=\"210\" y=\"373\" width=\"22\" height=\"22\"/>\n                    <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                    <buttonCell key=\"cell\" type=\"check\" bezelStyle=\"regularSquare\" imagePosition=\"left\" controlSize=\"large\" inset=\"2\" id=\"2wE-hu-3et\">\n                        <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\"/>\n                    </buttonCell>\n                </button>\n                <imageView horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"kuE-4D-Jtp\">\n                    <rect key=\"frame\" x=\"381\" y=\"366\" width=\"157\" height=\"86\"/>\n                    <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                    <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" image=\"screen0\" id=\"AEJ-Jx-6Th\"/>\n                </imageView>\n                <button verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"tp7-X6-tfK\">\n                    <rect key=\"frame\" x=\"386\" y=\"373\" width=\"22\" height=\"22\"/>\n                    <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                    <buttonCell key=\"cell\" type=\"check\" bezelStyle=\"regularSquare\" imagePosition=\"left\" controlSize=\"large\" state=\"on\" inset=\"2\" id=\"Y4o-FW-5Ty\">\n                        <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\"/>\n                    </buttonCell>\n                </button>\n                <imageView horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"fRe-U9-nvw\">\n                    <rect key=\"frame\" x=\"558\" y=\"366\" width=\"157\" height=\"86\"/>\n                    <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                    <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" image=\"screen0\" id=\"Q1N-Cj-m2i\"/>\n                </imageView>\n                <button verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"QmQ-fq-P0i\">\n                    <rect key=\"frame\" x=\"563\" y=\"373\" width=\"22\" height=\"22\"/>\n                    <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                    <buttonCell key=\"cell\" type=\"check\" bezelStyle=\"regularSquare\" imagePosition=\"left\" controlSize=\"large\" inset=\"2\" id=\"fOq-ID-Zvq\">\n                        <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\"/>\n                    </buttonCell>\n                </button>\n                <imageView horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"25H-dX-hC6\">\n                    <rect key=\"frame\" x=\"32\" y=\"264\" width=\"157\" height=\"86\"/>\n                    <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                    <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" image=\"screen0\" id=\"ogS-eu-h6A\"/>\n                </imageView>\n                <button verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"1Op-mm-eq6\">\n                    <rect key=\"frame\" x=\"37\" y=\"271\" width=\"22\" height=\"22\"/>\n                    <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                    <buttonCell key=\"cell\" type=\"check\" bezelStyle=\"regularSquare\" imagePosition=\"left\" controlSize=\"large\" state=\"on\" inset=\"2\" id=\"wqc-0i-SFA\">\n                        <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\"/>\n                    </buttonCell>\n                </button>\n                <imageView horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"1yx-rP-oRz\">\n                    <rect key=\"frame\" x=\"205\" y=\"264\" width=\"157\" height=\"86\"/>\n                    <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                    <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" image=\"screen0\" id=\"eXN-XS-adN\"/>\n                </imageView>\n                <button verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"9Eh-9u-4N0\">\n                    <rect key=\"frame\" x=\"210\" y=\"271\" width=\"22\" height=\"22\"/>\n                    <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                    <buttonCell key=\"cell\" type=\"check\" bezelStyle=\"regularSquare\" imagePosition=\"left\" controlSize=\"large\" inset=\"2\" id=\"gYi-j0-DrO\">\n                        <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\"/>\n                    </buttonCell>\n                </button>\n                <imageView horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Pk6-fE-TVk\">\n                    <rect key=\"frame\" x=\"381\" y=\"264\" width=\"157\" height=\"86\"/>\n                    <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                    <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" image=\"screen0\" id=\"NCh-Ba-63E\"/>\n                </imageView>\n                <button verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"FGL-Mz-W5G\">\n                    <rect key=\"frame\" x=\"386\" y=\"271\" width=\"22\" height=\"22\"/>\n                    <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                    <buttonCell key=\"cell\" type=\"check\" bezelStyle=\"regularSquare\" imagePosition=\"left\" controlSize=\"large\" inset=\"2\" id=\"kv8-7H-RdP\">\n                        <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\"/>\n                    </buttonCell>\n                </button>\n                <imageView horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"79A-ez-LaS\">\n                    <rect key=\"frame\" x=\"558\" y=\"264\" width=\"157\" height=\"86\"/>\n                    <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                    <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" image=\"screen0\" id=\"1BO-cH-zJu\"/>\n                </imageView>\n                <button verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"7gs-mu-PBs\">\n                    <rect key=\"frame\" x=\"563\" y=\"271\" width=\"22\" height=\"22\"/>\n                    <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                    <buttonCell key=\"cell\" type=\"check\" bezelStyle=\"regularSquare\" imagePosition=\"left\" controlSize=\"large\" state=\"on\" inset=\"2\" id=\"NvT-yG-Gng\">\n                        <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\"/>\n                    </buttonCell>\n                </button>\n                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"co9-eY-jDu\">\n                    <rect key=\"frame\" x=\"50\" y=\"223\" width=\"521\" height=\"16\"/>\n                    <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" title=\"21 corresponding videos are currently cached, new videos will be downloaded weekly\" id=\"5dZ-WW-X3d\">\n                        <font key=\"font\" metaFont=\"system\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <imageView horizontalHuggingPriority=\"25\" verticalHuggingPriority=\"25\" horizontalCompressionResistancePriority=\"75\" verticalCompressionResistancePriority=\"75\" ambiguous=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"k8L-x2-RH7\">\n                    <rect key=\"frame\" x=\"20\" y=\"167\" width=\"24\" height=\"30\"/>\n                    <constraints>\n                        <constraint firstAttribute=\"width\" constant=\"24\" id=\"8Eb-nd-RiO\"/>\n                    </constraints>\n                    <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" image=\"clock\" catalog=\"system\" id=\"hI2-xP-mhu\"/>\n                    <color key=\"contentTintColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                </imageView>\n                <customView ambiguous=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"5zr-l0-nWc\">\n                    <rect key=\"frame\" x=\"33\" y=\"64\" width=\"732\" height=\"96\"/>\n                    <subviews>\n                        <box boxType=\"custom\" title=\"Box\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"LTf-UZ-96b\">\n                            <rect key=\"frame\" x=\"12\" y=\"67\" width=\"152\" height=\"23\"/>\n                            <view key=\"contentView\" id=\"XGU-LZ-jBn\">\n                                <rect key=\"frame\" x=\"1\" y=\"1\" width=\"150\" height=\"21\"/>\n                                <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                                <subviews>\n                                    <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"fRh-ft-Upv\">\n                                        <rect key=\"frame\" x=\"59\" y=\"4\" width=\"33\" height=\"14\"/>\n                                        <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"Night\" id=\"BuJ-rR-DA1\">\n                                            <font key=\"font\" metaFont=\"smallSystem\"/>\n                                            <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                            <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                        </textFieldCell>\n                                    </textField>\n                                </subviews>\n                                <constraints>\n                                    <constraint firstItem=\"fRh-ft-Upv\" firstAttribute=\"centerY\" secondItem=\"XGU-LZ-jBn\" secondAttribute=\"centerY\" id=\"PBB-rP-glx\"/>\n                                    <constraint firstItem=\"fRh-ft-Upv\" firstAttribute=\"centerX\" secondItem=\"XGU-LZ-jBn\" secondAttribute=\"centerX\" id=\"Rsw-BH-TxD\"/>\n                                </constraints>\n                            </view>\n                            <constraints>\n                                <constraint firstAttribute=\"width\" constant=\"152\" id=\"Fr4-9Z-zCn\"/>\n                                <constraint firstAttribute=\"height\" constant=\"23\" id=\"Y3E-Hb-OWS\"/>\n                            </constraints>\n                            <color key=\"fillColor\" name=\"systemGrayColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        </box>\n                        <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"quS-6f-7X4\">\n                            <rect key=\"frame\" x=\"262\" y=\"48\" width=\"33\" height=\"16\"/>\n                            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                            <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"8:00\" id=\"s0D-hL-NcP\">\n                                <font key=\"font\" usesAppearanceFont=\"YES\"/>\n                                <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                            </textFieldCell>\n                        </textField>\n                        <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"lfD-xl-eHw\">\n                            <rect key=\"frame\" x=\"148\" y=\"48\" width=\"33\" height=\"16\"/>\n                            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                            <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"4:00\" id=\"Ewf-N3-VAQ\">\n                                <font key=\"font\" usesAppearanceFont=\"YES\"/>\n                                <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                            </textFieldCell>\n                        </textField>\n                        <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Om6-D4-0HR\">\n                            <rect key=\"frame\" x=\"-2\" y=\"48\" width=\"33\" height=\"16\"/>\n                            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                            <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"0:00\" id=\"Ec0-CJ-NnX\">\n                                <font key=\"font\" usesAppearanceFont=\"YES\"/>\n                                <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                            </textFieldCell>\n                        </textField>\n                        <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"zxf-hQ-g64\">\n                            <rect key=\"frame\" x=\"454\" y=\"48\" width=\"39\" height=\"16\"/>\n                            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                            <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"19:00\" id=\"KO6-zq-YX2\">\n                                <font key=\"font\" usesAppearanceFont=\"YES\"/>\n                                <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                            </textFieldCell>\n                        </textField>\n                        <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"rA0-6E-B4L\">\n                            <rect key=\"frame\" x=\"694\" y=\"48\" width=\"40\" height=\"16\"/>\n                            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                            <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"23:59\" id=\"YcI-pZ-5Gd\">\n                                <font key=\"font\" usesAppearanceFont=\"YES\"/>\n                                <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                            </textFieldCell>\n                        </textField>\n                        <box boxType=\"custom\" title=\"Box\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"eD2-m3-q8c\">\n                            <rect key=\"frame\" x=\"468\" y=\"67\" width=\"105\" height=\"23\"/>\n                            <view key=\"contentView\" id=\"nl5-tW-1Em\">\n                                <rect key=\"frame\" x=\"1\" y=\"1\" width=\"103\" height=\"21\"/>\n                                <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                                <subviews>\n                                    <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"VOT-dK-j7A\">\n                                        <rect key=\"frame\" x=\"31\" y=\"4\" width=\"41\" height=\"14\"/>\n                                        <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"Sunset\" id=\"nZl-jn-vPA\">\n                                            <font key=\"font\" metaFont=\"smallSystem\"/>\n                                            <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                            <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                        </textFieldCell>\n                                    </textField>\n                                </subviews>\n                                <constraints>\n                                    <constraint firstItem=\"VOT-dK-j7A\" firstAttribute=\"centerY\" secondItem=\"nl5-tW-1Em\" secondAttribute=\"centerY\" id=\"Oed-j5-Z8y\"/>\n                                    <constraint firstItem=\"VOT-dK-j7A\" firstAttribute=\"centerX\" secondItem=\"nl5-tW-1Em\" secondAttribute=\"centerX\" id=\"zm4-Se-RDl\"/>\n                                </constraints>\n                            </view>\n                            <constraints>\n                                <constraint firstAttribute=\"width\" constant=\"105\" id=\"5Fe-lU-S2a\"/>\n                                <constraint firstAttribute=\"height\" constant=\"23\" id=\"ya2-By-ano\"/>\n                            </constraints>\n                            <color key=\"fillColor\" name=\"systemOrangeColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        </box>\n                        <box boxType=\"custom\" title=\"Box\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"5jv-v2-Lcs\">\n                            <rect key=\"frame\" x=\"276\" y=\"67\" width=\"193\" height=\"23\"/>\n                            <view key=\"contentView\" id=\"IYh-VE-wJI\">\n                                <rect key=\"frame\" x=\"1\" y=\"1\" width=\"191\" height=\"21\"/>\n                                <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                                <subviews>\n                                    <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Sx5-D5-H0Z\">\n                                        <rect key=\"frame\" x=\"83\" y=\"4\" width=\"25\" height=\"14\"/>\n                                        <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"Day\" id=\"a1q-kG-RyU\">\n                                            <font key=\"font\" metaFont=\"smallSystem\"/>\n                                            <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                            <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                        </textFieldCell>\n                                    </textField>\n                                </subviews>\n                                <constraints>\n                                    <constraint firstItem=\"Sx5-D5-H0Z\" firstAttribute=\"centerY\" secondItem=\"IYh-VE-wJI\" secondAttribute=\"centerY\" id=\"TYA-Sp-hnq\"/>\n                                    <constraint firstItem=\"Sx5-D5-H0Z\" firstAttribute=\"centerX\" secondItem=\"IYh-VE-wJI\" secondAttribute=\"centerX\" id=\"qz5-JR-oHk\"/>\n                                </constraints>\n                            </view>\n                            <constraints>\n                                <constraint firstAttribute=\"height\" constant=\"23\" id=\"XsN-Sy-ty6\"/>\n                                <constraint firstAttribute=\"width\" constant=\"193\" id=\"m87-2W-ChU\"/>\n                            </constraints>\n                            <color key=\"fillColor\" name=\"systemTealColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        </box>\n                        <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"nZS-6F-95b\">\n                            <rect key=\"frame\" x=\"554\" y=\"48\" width=\"40\" height=\"16\"/>\n                            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                            <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"22:00\" id=\"hle-Ji-I5w\">\n                                <font key=\"font\" usesAppearanceFont=\"YES\"/>\n                                <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                            </textFieldCell>\n                        </textField>\n                        <box boxType=\"custom\" title=\"Box\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"HRb-tQ-S8F\">\n                            <rect key=\"frame\" x=\"572\" y=\"67\" width=\"144\" height=\"23\"/>\n                            <view key=\"contentView\" id=\"WGF-ZC-a4l\">\n                                <rect key=\"frame\" x=\"1\" y=\"1\" width=\"142\" height=\"21\"/>\n                                <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                                <subviews>\n                                    <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"YgA-xG-UbQ\">\n                                        <rect key=\"frame\" x=\"55\" y=\"4\" width=\"33\" height=\"14\"/>\n                                        <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"Night\" id=\"PyQ-Dc-aXW\">\n                                            <font key=\"font\" metaFont=\"smallSystem\"/>\n                                            <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                            <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                        </textFieldCell>\n                                    </textField>\n                                </subviews>\n                                <constraints>\n                                    <constraint firstItem=\"YgA-xG-UbQ\" firstAttribute=\"centerX\" secondItem=\"WGF-ZC-a4l\" secondAttribute=\"centerX\" id=\"2Zn-2d-wvX\"/>\n                                    <constraint firstItem=\"YgA-xG-UbQ\" firstAttribute=\"centerY\" secondItem=\"WGF-ZC-a4l\" secondAttribute=\"centerY\" id=\"U1L-Wl-MxI\"/>\n                                </constraints>\n                            </view>\n                            <constraints>\n                                <constraint firstAttribute=\"width\" constant=\"144\" id=\"0mF-tg-qmw\"/>\n                                <constraint firstAttribute=\"height\" constant=\"23\" id=\"CU7-vu-Uts\"/>\n                            </constraints>\n                            <color key=\"fillColor\" name=\"systemGrayColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        </box>\n                        <box boxType=\"custom\" title=\"Box\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"DNo-fa-z2E\">\n                            <rect key=\"frame\" x=\"163\" y=\"67\" width=\"114\" height=\"23\"/>\n                            <view key=\"contentView\" id=\"E1E-GC-mdi\">\n                                <rect key=\"frame\" x=\"1\" y=\"1\" width=\"112\" height=\"21\"/>\n                                <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                                <subviews>\n                                    <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"E7X-Ts-qFc\">\n                                        <rect key=\"frame\" x=\"34\" y=\"4\" width=\"44\" height=\"14\"/>\n                                        <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"Sunrise\" id=\"Vxh-cb-N4S\">\n                                            <font key=\"font\" metaFont=\"smallSystem\"/>\n                                            <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                            <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                        </textFieldCell>\n                                    </textField>\n                                </subviews>\n                                <constraints>\n                                    <constraint firstItem=\"E7X-Ts-qFc\" firstAttribute=\"centerX\" secondItem=\"E1E-GC-mdi\" secondAttribute=\"centerX\" id=\"lMH-FN-Rxf\"/>\n                                    <constraint firstItem=\"E7X-Ts-qFc\" firstAttribute=\"centerY\" secondItem=\"E1E-GC-mdi\" secondAttribute=\"centerY\" id=\"mzV-fI-aag\"/>\n                                </constraints>\n                            </view>\n                            <constraints>\n                                <constraint firstAttribute=\"height\" constant=\"23\" id=\"ERW-Dh-U3U\"/>\n                                <constraint firstAttribute=\"width\" constant=\"114\" id=\"hCv-MA-ncl\"/>\n                            </constraints>\n                            <color key=\"fillColor\" name=\"systemPurpleColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        </box>\n                        <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"gYb-i8-tga\">\n                            <rect key=\"frame\" x=\"58\" y=\"20\" width=\"60\" height=\"32\"/>\n                            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                            <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" id=\"3cr-MN-hHQ\">\n                                <font key=\"font\" metaFont=\"system\"/>\n                                <string key=\"title\">5 videos\n2 cached</string>\n                                <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                            </textFieldCell>\n                        </textField>\n                        <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"BaY-A2-L3z\">\n                            <rect key=\"frame\" x=\"190\" y=\"20\" width=\"61\" height=\"32\"/>\n                            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                            <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" id=\"Q9U-7r-irg\">\n                                <font key=\"font\" metaFont=\"system\"/>\n                                <string key=\"title\">4 videos\n4 cached</string>\n                                <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                            </textFieldCell>\n                        </textField>\n                        <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"fw4-qa-3oO\">\n                            <rect key=\"frame\" x=\"339\" y=\"20\" width=\"66\" height=\"32\"/>\n                            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                            <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" id=\"1EL-ut-u8k\">\n                                <font key=\"font\" metaFont=\"system\"/>\n                                <string key=\"title\">25 videos\n12 cached</string>\n                                <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                            </textFieldCell>\n                        </textField>\n                        <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"56g-ZV-jOM\">\n                            <rect key=\"frame\" x=\"490\" y=\"20\" width=\"61\" height=\"32\"/>\n                            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                            <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" id=\"9v0-1F-C6t\">\n                                <font key=\"font\" metaFont=\"system\"/>\n                                <string key=\"title\">4 videos\n4 cached</string>\n                                <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                            </textFieldCell>\n                        </textField>\n                        <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"1wi-4W-1Tu\">\n                            <rect key=\"frame\" x=\"614\" y=\"20\" width=\"61\" height=\"32\"/>\n                            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                            <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" id=\"sEk-0N-uwz\">\n                                <font key=\"font\" metaFont=\"system\"/>\n                                <string key=\"title\">4 videos\n4 cached</string>\n                                <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                            </textFieldCell>\n                        </textField>\n                    </subviews>\n                    <constraints>\n                        <constraint firstItem=\"5jv-v2-Lcs\" firstAttribute=\"centerY\" secondItem=\"DNo-fa-z2E\" secondAttribute=\"centerY\" id=\"4PO-G3-djE\"/>\n                        <constraint firstItem=\"5jv-v2-Lcs\" firstAttribute=\"leading\" secondItem=\"DNo-fa-z2E\" secondAttribute=\"trailing\" constant=\"-1\" id=\"8ts-0H-zoD\"/>\n                        <constraint firstItem=\"HRb-tQ-S8F\" firstAttribute=\"leading\" secondItem=\"eD2-m3-q8c\" secondAttribute=\"trailing\" constant=\"-1\" id=\"Aca-5S-pRB\"/>\n                        <constraint firstItem=\"eD2-m3-q8c\" firstAttribute=\"centerY\" secondItem=\"DNo-fa-z2E\" secondAttribute=\"centerY\" id=\"Q6C-A7-5CH\"/>\n                        <constraint firstItem=\"eD2-m3-q8c\" firstAttribute=\"leading\" secondItem=\"5jv-v2-Lcs\" secondAttribute=\"trailing\" constant=\"-1\" id=\"QGd-39-U1i\"/>\n                        <constraint firstItem=\"DNo-fa-z2E\" firstAttribute=\"centerY\" secondItem=\"LTf-UZ-96b\" secondAttribute=\"centerY\" id=\"Ux4-pS-mFl\"/>\n                        <constraint firstItem=\"HRb-tQ-S8F\" firstAttribute=\"centerY\" secondItem=\"DNo-fa-z2E\" secondAttribute=\"centerY\" id=\"dt5-gu-7nk\"/>\n                        <constraint firstItem=\"LTf-UZ-96b\" firstAttribute=\"leading\" secondItem=\"5zr-l0-nWc\" secondAttribute=\"leading\" constant=\"12\" id=\"fkQ-Ec-fTm\"/>\n                        <constraint firstAttribute=\"width\" constant=\"732\" id=\"hVg-Ha-dWj\"/>\n                        <constraint firstItem=\"LTf-UZ-96b\" firstAttribute=\"top\" secondItem=\"5zr-l0-nWc\" secondAttribute=\"top\" id=\"hyJ-dn-Zv4\"/>\n                        <constraint firstAttribute=\"height\" constant=\"90\" id=\"kGl-xy-qN0\"/>\n                        <constraint firstItem=\"DNo-fa-z2E\" firstAttribute=\"leading\" secondItem=\"LTf-UZ-96b\" secondAttribute=\"trailing\" constant=\"-1\" id=\"ptz-7r-eRY\"/>\n                    </constraints>\n                </customView>\n                <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"bKh-aV-A9M\">\n                    <rect key=\"frame\" x=\"50\" y=\"174\" width=\"274\" height=\"16\"/>\n                    <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                    <textFieldCell key=\"cell\" controlSize=\"large\" lineBreakMode=\"clipping\" title=\"Videos shown will depend on the time of day\" id=\"tVa-yy-Mj1\">\n                        <font key=\"font\" metaFont=\"system\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <button verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"P5n-w9-EEu\">\n                    <rect key=\"frame\" x=\"585\" y=\"215\" width=\"198\" height=\"32\"/>\n                    <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                    <buttonCell key=\"cell\" type=\"push\" title=\"Change cache settings\" bezelStyle=\"rounded\" image=\"externaldrive\" catalog=\"system\" imagePosition=\"leading\" alignment=\"center\" controlSize=\"large\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"JTr-Oa-hZB\">\n                        <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\"/>\n                    </buttonCell>\n                </button>\n                <button verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"78X-hv-qh5\">\n                    <rect key=\"frame\" x=\"585\" y=\"166\" width=\"198\" height=\"32\"/>\n                    <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                    <buttonCell key=\"cell\" type=\"push\" title=\"Change time settings\" bezelStyle=\"rounded\" image=\"clock\" catalog=\"system\" imagePosition=\"left\" alignment=\"center\" controlSize=\"large\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"1u8-XK-Owx\">\n                        <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\"/>\n                    </buttonCell>\n                </button>\n            </subviews>\n            <constraints>\n                <constraint firstItem=\"zyI-GA-Pn4\" firstAttribute=\"leading\" secondItem=\"R5E-Ac-s6u\" secondAttribute=\"trailing\" constant=\"10\" id=\"JOy-Gk-HOA\"/>\n                <constraint firstItem=\"zyI-GA-Pn4\" firstAttribute=\"firstBaseline\" secondItem=\"R5E-Ac-s6u\" secondAttribute=\"firstBaseline\" id=\"QTN-xl-2g1\"/>\n                <constraint firstItem=\"R5E-Ac-s6u\" firstAttribute=\"leading\" secondItem=\"r3Q-f4-uvO\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"nEE-Up-cJi\"/>\n            </constraints>\n            <point key=\"canvasLocation\" x=\"220.5\" y=\"551\"/>\n        </customView>\n    </objects>\n    <resources>\n        <image name=\"NSTouchBarDownloadTemplate\" width=\"20\" height=\"20\"/>\n        <image name=\"arrow.down.circle\" width=\"141\" height=\"155\"/>\n        <image name=\"arrow.down.circle.fill\" width=\"141\" height=\"155\"/>\n        <image name=\"book\" catalog=\"system\" width=\"18\" height=\"14\"/>\n        <image name=\"clock\" catalog=\"system\" width=\"15\" height=\"15\"/>\n        <image name=\"externaldrive\" catalog=\"system\" width=\"18\" height=\"13\"/>\n        <image name=\"eye\" catalog=\"system\" width=\"21\" height=\"13\"/>\n        <image name=\"eye.slash\" catalog=\"system\" width=\"21\" height=\"16\"/>\n        <image name=\"film\" catalog=\"system\" width=\"18\" height=\"14\"/>\n        <image name=\"internaldrive\" catalog=\"system\" width=\"18\" height=\"13\"/>\n        <image name=\"leaf\" catalog=\"system\" width=\"16\" height=\"14\"/>\n        <image name=\"location\" catalog=\"system\" width=\"15\" height=\"15\"/>\n        <image name=\"play\" catalog=\"system\" width=\"12\" height=\"13\"/>\n        <image name=\"screen0\" width=\"720\" height=\"400\"/>\n        <image name=\"star\" catalog=\"system\" width=\"17\" height=\"16\"/>\n        <image name=\"star\" width=\"154\" height=\"166\"/>\n        <image name=\"star.fill\" width=\"154\" height=\"166\"/>\n        <image name=\"sun.max\" width=\"147\" height=\"168\"/>\n        <image name=\"video.badge.plus\" catalog=\"system\" width=\"21\" height=\"16\"/>\n    </resources>\n</document>\n"
  },
  {
    "path": "Resources/Old stuff/CustomVideos.xib",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.Cocoa.XIB\" version=\"3.0\" toolsVersion=\"17154\" targetRuntime=\"MacOSX.Cocoa\" propertyAccessControl=\"none\" useAutolayout=\"YES\" customObjectInstantitationMethod=\"direct\">\n    <dependencies>\n        <deployment identifier=\"macosx\"/>\n        <plugIn identifier=\"com.apple.AVKitIBPlugin\" version=\"17154\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.CocoaPlugin\" version=\"17154\"/>\n        <capability name=\"documents saved in the Xcode 8 format\" minToolsVersion=\"8.0\"/>\n    </dependencies>\n    <objects>\n        <customObject id=\"-2\" userLabel=\"File's Owner\" customClass=\"CustomVideoController\" customModule=\"Aerial\" customModuleProvider=\"target\">\n            <connections>\n                <outlet property=\"addFolderCatalinaPanel\" destination=\"Atl-SY-oen\" id=\"alS-HU-bxF\"/>\n                <outlet property=\"addFolderTextField\" destination=\"npi-Wy-4IZ\" id=\"cCp-RQ-4Hz\"/>\n                <outlet property=\"addPoi\" destination=\"KBT-QW-v1Y\" id=\"mgo-Tc-dzf\"/>\n                <outlet property=\"addPoiPopover\" destination=\"6xN-bb-mFa\" id=\"ZoY-sG-uBj\"/>\n                <outlet property=\"cvcMenu\" destination=\"bRP-nE-M4C\" id=\"Pb2-QB-adU\"/>\n                <outlet property=\"descriptionTextField\" destination=\"3KO-Vs-fx0\" id=\"8Hk-eS-HvF\"/>\n                <outlet property=\"durationLabel\" destination=\"2Y8-Ra-MML\" id=\"Yli-Hc-JAX\"/>\n                <outlet property=\"editPlayerView\" destination=\"PnC-8m-1v6\" id=\"qS2-DG-dnh\"/>\n                <outlet property=\"fileView\" destination=\"Nz4-zd-m53\" id=\"GG8-xr-Lm6\"/>\n                <outlet property=\"folderOutlineView\" destination=\"NS6-lm-7hO\" id=\"dek-Xm-0hw\"/>\n                <outlet property=\"folderShortNameTextField\" destination=\"MFU-Dj-anp\" id=\"uCp-AT-vUi\"/>\n                <outlet property=\"folderView\" destination=\"k3L-uV-wCN\" id=\"mco-c5-WPA\"/>\n                <outlet property=\"mainPanel\" destination=\"QvC-M9-y7g\" id=\"of1-JA-evN\"/>\n                <outlet property=\"menuRemoveFolderAndVideos\" destination=\"hea-rl-zIh\" id=\"cgK-fx-fhH\"/>\n                <outlet property=\"menuRemoveVideo\" destination=\"ytF-SB-6AJ\" id=\"AHB-c4-ulp\"/>\n                <outlet property=\"onboardingLabel\" destination=\"zeW-AH-yaN\" id=\"YQc-15-2jO\"/>\n                <outlet property=\"poiTableView\" destination=\"n5i-pm-jIu\" id=\"Uns-u2-Hf9\"/>\n                <outlet property=\"removePoi\" destination=\"EBI-tO-TJo\" id=\"w10-SS-DnA\"/>\n                <outlet property=\"resolutionLabel\" destination=\"HdI-qF-NRI\" id=\"9l4-zp-gM7\"/>\n                <outlet property=\"timePopUpButton\" destination=\"6cg-pb-yCE\" id=\"6aq-zq-oTy\"/>\n                <outlet property=\"timeTextField\" destination=\"SpE-ag-aCO\" id=\"vCQ-5I-aLR\"/>\n                <outlet property=\"timeTextFormatter\" destination=\"Ixe-Fx-2fC\" id=\"jh8-Z9-AMe\"/>\n                <outlet property=\"timeTextStepper\" destination=\"Zrt-uf-nIH\" id=\"E4f-xd-pht\"/>\n                <outlet property=\"topPathControl\" destination=\"aLi-9f-2VM\" id=\"HY7-Se-sE3\"/>\n                <outlet property=\"videoNameTextField\" destination=\"kpy-af-zIL\" id=\"4ac-rk-8p8\"/>\n            </connections>\n        </customObject>\n        <customObject id=\"-1\" userLabel=\"First Responder\" customClass=\"FirstResponder\"/>\n        <customObject id=\"-3\" userLabel=\"Application\" customClass=\"NSObject\"/>\n        <window title=\"Manage Local Videos\" allowsToolTipsWhenApplicationIsInactive=\"NO\" autorecalculatesKeyViewLoop=\"NO\" releasedWhenClosed=\"NO\" visibleAtLaunch=\"NO\" animationBehavior=\"default\" titlebarAppearsTransparent=\"YES\" titleVisibility=\"hidden\" id=\"QvC-M9-y7g\" customClass=\"NSPanel\">\n            <windowStyleMask key=\"styleMask\" titled=\"YES\" closable=\"YES\" miniaturizable=\"YES\" resizable=\"YES\"/>\n            <windowPositionMask key=\"initialPositionMask\" leftStrut=\"YES\" rightStrut=\"YES\" topStrut=\"YES\" bottomStrut=\"YES\"/>\n            <rect key=\"contentRect\" x=\"196\" y=\"240\" width=\"1163\" height=\"630\"/>\n            <rect key=\"screenRect\" x=\"0.0\" y=\"0.0\" width=\"2560\" height=\"1415\"/>\n            <view key=\"contentView\" wantsLayer=\"YES\" id=\"EiT-Mj-1SZ\">\n                <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"1163\" height=\"630\"/>\n                <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                <subviews>\n                    <splitView fixedFrame=\"YES\" arrangesAllSubviews=\"NO\" dividerStyle=\"paneSplitter\" vertical=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Mu6-6s-BT8\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"1163\" height=\"631\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <subviews>\n                            <customView fixedFrame=\"YES\" id=\"en0-aC-aMt\">\n                                <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"213\" height=\"631\"/>\n                                <autoresizingMask key=\"autoresizingMask\"/>\n                                <subviews>\n                                    <scrollView fixedFrame=\"YES\" autohidesScrollers=\"YES\" horizontalLineScroll=\"19\" horizontalPageScroll=\"10\" verticalLineScroll=\"19\" verticalPageScroll=\"10\" usesPredominantAxisScrolling=\"NO\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"ul4-fX-U4v\">\n                                        <rect key=\"frame\" x=\"0.0\" y=\"-1\" width=\"213\" height=\"632\"/>\n                                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                                        <clipView key=\"contentView\" id=\"Ril-bY-Guv\">\n                                            <rect key=\"frame\" x=\"1\" y=\"1\" width=\"211\" height=\"630\"/>\n                                            <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                                            <subviews>\n                                                <outlineView verticalHuggingPriority=\"750\" allowsExpansionToolTips=\"YES\" columnAutoresizingStyle=\"lastColumnOnly\" multipleSelection=\"NO\" autosaveColumns=\"NO\" rowSizeStyle=\"automatic\" viewBased=\"YES\" indentationPerLevel=\"16\" autoresizesOutlineColumn=\"YES\" outlineTableColumn=\"OM8-ZD-XmW\" id=\"NS6-lm-7hO\">\n                                                    <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"211\" height=\"630\"/>\n                                                    <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                                                    <size key=\"intercellSpacing\" width=\"3\" height=\"2\"/>\n                                                    <color key=\"backgroundColor\" name=\"controlBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                    <color key=\"gridColor\" name=\"gridColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                    <tableColumns>\n                                                        <tableColumn identifier=\"folderColumn\" width=\"199\" minWidth=\"40\" maxWidth=\"1000\" id=\"OM8-ZD-XmW\">\n                                                            <tableHeaderCell key=\"headerCell\" lineBreakMode=\"truncatingTail\" borderStyle=\"border\">\n                                                                <color key=\"textColor\" name=\"headerTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                                <color key=\"backgroundColor\" name=\"headerColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                            </tableHeaderCell>\n                                                            <textFieldCell key=\"dataCell\" lineBreakMode=\"truncatingTail\" selectable=\"YES\" editable=\"YES\" title=\"Text Cell\" id=\"nHs-Sa-o9b\">\n                                                                <font key=\"font\" metaFont=\"system\"/>\n                                                                <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                                <color key=\"backgroundColor\" name=\"controlBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                            </textFieldCell>\n                                                            <tableColumnResizingMask key=\"resizingMask\" resizeWithTable=\"YES\" userResizable=\"YES\"/>\n                                                            <prototypeCellViews>\n                                                                <tableCellView identifier=\"folderCell\" id=\"7Ix-SV-cB3\">\n                                                                    <rect key=\"frame\" x=\"11\" y=\"1\" width=\"208\" height=\"17\"/>\n                                                                    <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                                                                    <subviews>\n                                                                        <textField verticalHuggingPriority=\"750\" horizontalCompressionResistancePriority=\"250\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"pow-vD-4Sa\">\n                                                                            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"208\" height=\"17\"/>\n                                                                            <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" flexibleMinY=\"YES\"/>\n                                                                            <textFieldCell key=\"cell\" lineBreakMode=\"truncatingTail\" sendsActionOnEndEditing=\"YES\" title=\"Table View Cell\" id=\"LPS-pW-3MS\">\n                                                                                <font key=\"font\" metaFont=\"system\"/>\n                                                                                <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                                                <color key=\"backgroundColor\" name=\"controlColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                                            </textFieldCell>\n                                                                        </textField>\n                                                                    </subviews>\n                                                                    <connections>\n                                                                        <outlet property=\"textField\" destination=\"pow-vD-4Sa\" id=\"VVd-1F-56g\"/>\n                                                                    </connections>\n                                                                </tableCellView>\n                                                            </prototypeCellViews>\n                                                        </tableColumn>\n                                                    </tableColumns>\n                                                </outlineView>\n                                            </subviews>\n                                        </clipView>\n                                        <scroller key=\"horizontalScroller\" hidden=\"YES\" wantsLayer=\"YES\" verticalHuggingPriority=\"750\" horizontal=\"YES\" id=\"zn4-7t-qkl\">\n                                            <rect key=\"frame\" x=\"1\" y=\"615\" width=\"211\" height=\"16\"/>\n                                            <autoresizingMask key=\"autoresizingMask\"/>\n                                        </scroller>\n                                        <scroller key=\"verticalScroller\" hidden=\"YES\" wantsLayer=\"YES\" verticalHuggingPriority=\"750\" horizontal=\"NO\" id=\"Mv2-tb-xir\">\n                                            <rect key=\"frame\" x=\"224\" y=\"17\" width=\"15\" height=\"102\"/>\n                                            <autoresizingMask key=\"autoresizingMask\"/>\n                                        </scroller>\n                                    </scrollView>\n                                </subviews>\n                            </customView>\n                            <customView fixedFrame=\"YES\" id=\"WJW-Ii-tgN\">\n                                <rect key=\"frame\" x=\"223\" y=\"0.0\" width=\"940\" height=\"631\"/>\n                                <autoresizingMask key=\"autoresizingMask\"/>\n                                <subviews>\n                                    <textField verticalHuggingPriority=\"750\" horizontalCompressionResistancePriority=\"250\" fixedFrame=\"YES\" preferredMaxLayoutWidth=\"862\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"zeW-AH-yaN\">\n                                        <rect key=\"frame\" x=\"37\" y=\"307\" width=\"866\" height=\"80\"/>\n                                        <autoresizingMask key=\"autoresizingMask\" flexibleMinX=\"YES\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\" flexibleMaxY=\"YES\"/>\n                                        <textFieldCell key=\"cell\" selectable=\"YES\" alignment=\"center\" id=\"4j6-f0-YpW\">\n                                            <font key=\"font\" usesAppearanceFont=\"YES\"/>\n                                            <string key=\"title\">Click the \"+ Add Folder\" button on top of the window. You can also drag a folder into the left column.\n\nStarting with macOS 10.15, we highly recommend you put your videos in a folder in /Users/Shared/. Because of security restrictions that were introduced, locations such as Desktop, Documents, Downloads, or external drive are not possible. </string>\n                                            <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                            <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                        </textFieldCell>\n                                    </textField>\n                                    <customView fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"k3L-uV-wCN\" userLabel=\"Folder Panel\">\n                                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"940\" height=\"598\"/>\n                                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                                        <subviews>\n                                            <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"zLj-As-xCy\">\n                                                <rect key=\"frame\" x=\"18\" y=\"561\" width=\"80\" height=\"17\"/>\n                                                <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                                                <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"Folder name\" id=\"1M5-BC-Hc7\">\n                                                    <font key=\"font\" usesAppearanceFont=\"YES\"/>\n                                                    <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                    <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                </textFieldCell>\n                                            </textField>\n                                            <textField verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"MFU-Dj-anp\">\n                                                <rect key=\"frame\" x=\"111\" y=\"558\" width=\"307\" height=\"22\"/>\n                                                <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                                                <textFieldCell key=\"cell\" scrollable=\"YES\" lineBreakMode=\"clipping\" selectable=\"YES\" editable=\"YES\" sendsActionOnEndEditing=\"YES\" borderStyle=\"bezel\" drawsBackground=\"YES\" id=\"iVE-cu-j8X\">\n                                                    <font key=\"font\" metaFont=\"system\"/>\n                                                    <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                    <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                </textFieldCell>\n                                                <connections>\n                                                    <action selector=\"folderNameChange:\" target=\"-2\" id=\"Vv1-Si-Adi\"/>\n                                                </connections>\n                                            </textField>\n                                            <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"CpZ-p1-5zy\">\n                                                <rect key=\"frame\" x=\"119\" y=\"533\" width=\"278\" height=\"14\"/>\n                                                <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                                                <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"This folder's videos will be grouped under this name\" id=\"hzy-ab-uSN\">\n                                                    <font key=\"font\" metaFont=\"label\" size=\"11\"/>\n                                                    <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                    <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                </textFieldCell>\n                                            </textField>\n                                        </subviews>\n                                    </customView>\n                                    <customView identifier=\"pathBar\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"cal-OI-2s3\" userLabel=\"Path bar\">\n                                        <rect key=\"frame\" x=\"0.0\" y=\"598\" width=\"940\" height=\"33\"/>\n                                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" flexibleMinY=\"YES\"/>\n                                        <subviews>\n                                            <pathControl verticalHuggingPriority=\"750\" fixedFrame=\"YES\" allowsExpansionToolTips=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"aLi-9f-2VM\">\n                                                <rect key=\"frame\" x=\"11\" y=\"7\" width=\"915\" height=\"18\"/>\n                                                <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" flexibleMinY=\"YES\"/>\n                                                <pathCell key=\"cell\" controlSize=\"small\" selectable=\"YES\" alignment=\"left\" id=\"erg-pd-yEU\">\n                                                    <font key=\"font\" metaFont=\"label\" size=\"11\"/>\n                                                    <url key=\"url\" string=\"file://localhost/Applications/\"/>\n                                                </pathCell>\n                                            </pathControl>\n                                        </subviews>\n                                    </customView>\n                                    <customView identifier=\"folderEdit\" hidden=\"YES\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Nz4-zd-m53\">\n                                        <rect key=\"frame\" x=\"0.0\" y=\"1\" width=\"940\" height=\"598\"/>\n                                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                                        <subviews>\n                                            <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"DWo-O9-7MP\">\n                                                <rect key=\"frame\" x=\"18\" y=\"562\" width=\"76\" height=\"17\"/>\n                                                <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                                                <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"Video name\" id=\"tCe-xi-F6Y\">\n                                                    <font key=\"font\" usesAppearanceFont=\"YES\"/>\n                                                    <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                    <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                </textFieldCell>\n                                            </textField>\n                                            <textField verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"kpy-af-zIL\">\n                                                <rect key=\"frame\" x=\"107\" y=\"557\" width=\"315\" height=\"22\"/>\n                                                <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                                                <textFieldCell key=\"cell\" scrollable=\"YES\" lineBreakMode=\"clipping\" selectable=\"YES\" editable=\"YES\" sendsActionOnEndEditing=\"YES\" borderStyle=\"bezel\" drawsBackground=\"YES\" id=\"IuS-qh-zHw\">\n                                                    <font key=\"font\" metaFont=\"system\"/>\n                                                    <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                    <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                </textFieldCell>\n                                                <connections>\n                                                    <action selector=\"videoNameChange:\" target=\"-2\" id=\"690-wv-GlG\"/>\n                                                </connections>\n                                            </textField>\n                                            <scrollView fixedFrame=\"YES\" autohidesScrollers=\"YES\" horizontalLineScroll=\"19\" horizontalPageScroll=\"10\" verticalLineScroll=\"19\" verticalPageScroll=\"10\" usesPredominantAxisScrolling=\"NO\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Uy6-Ie-8rV\">\n                                                <rect key=\"frame\" x=\"20\" y=\"259\" width=\"858\" height=\"284\"/>\n                                                <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                                                <clipView key=\"contentView\" id=\"0zj-Gi-fFA\">\n                                                    <rect key=\"frame\" x=\"1\" y=\"1\" width=\"856\" height=\"282\"/>\n                                                    <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                                                    <subviews>\n                                                        <tableView verticalHuggingPriority=\"750\" allowsExpansionToolTips=\"YES\" columnAutoresizingStyle=\"none\" alternatingRowBackgroundColors=\"YES\" columnReordering=\"NO\" columnSelection=\"YES\" multipleSelection=\"NO\" autosaveColumns=\"NO\" rowSizeStyle=\"automatic\" headerView=\"bx5-5m-J3h\" viewBased=\"YES\" id=\"n5i-pm-jIu\">\n                                                            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"907\" height=\"257\"/>\n                                                            <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                                                            <size key=\"intercellSpacing\" width=\"3\" height=\"2\"/>\n                                                            <color key=\"backgroundColor\" name=\"controlBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                            <color key=\"gridColor\" name=\"gridColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                            <tableColumns>\n                                                                <tableColumn identifier=\"timeColumn\" width=\"98\" minWidth=\"40\" maxWidth=\"1000\" id=\"iH3-Dm-5Ct\">\n                                                                    <tableHeaderCell key=\"headerCell\" lineBreakMode=\"truncatingTail\" borderStyle=\"border\" title=\"Time in seconds\">\n                                                                        <color key=\"textColor\" name=\"headerTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                                        <color key=\"backgroundColor\" name=\"headerColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                                    </tableHeaderCell>\n                                                                    <textFieldCell key=\"dataCell\" lineBreakMode=\"truncatingTail\" selectable=\"YES\" editable=\"YES\" title=\"Text Cell\" id=\"Vyv-Jh-MOo\">\n                                                                        <font key=\"font\" metaFont=\"system\"/>\n                                                                        <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                                        <color key=\"backgroundColor\" name=\"controlBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                                    </textFieldCell>\n                                                                    <tableColumnResizingMask key=\"resizingMask\" resizeWithTable=\"YES\" userResizable=\"YES\"/>\n                                                                    <prototypeCellViews>\n                                                                        <tableCellView id=\"cJh-BN-UxP\">\n                                                                            <rect key=\"frame\" x=\"11\" y=\"1\" width=\"103\" height=\"17\"/>\n                                                                            <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                                                                            <subviews>\n                                                                                <textField verticalHuggingPriority=\"750\" horizontalCompressionResistancePriority=\"250\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"b7k-LO-ye4\">\n                                                                                    <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"103\" height=\"17\"/>\n                                                                                    <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" flexibleMinY=\"YES\"/>\n                                                                                    <textFieldCell key=\"cell\" lineBreakMode=\"truncatingTail\" selectable=\"YES\" editable=\"YES\" sendsActionOnEndEditing=\"YES\" title=\"Table View Cell\" id=\"Nof-g1-FBo\">\n                                                                                        <font key=\"font\" metaFont=\"system\"/>\n                                                                                        <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                                                        <color key=\"backgroundColor\" name=\"controlColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                                                    </textFieldCell>\n                                                                                    <connections>\n                                                                                        <action selector=\"tableViewTimeField:\" target=\"-2\" id=\"wej-Wv-W1z\"/>\n                                                                                    </connections>\n                                                                                </textField>\n                                                                            </subviews>\n                                                                            <connections>\n                                                                                <outlet property=\"textField\" destination=\"b7k-LO-ye4\" id=\"hkv-V0-d5A\"/>\n                                                                            </connections>\n                                                                        </tableCellView>\n                                                                    </prototypeCellViews>\n                                                                </tableColumn>\n                                                                <tableColumn identifier=\"descriptionColumn\" width=\"794\" minWidth=\"40\" maxWidth=\"1000\" id=\"mnB-px-Eew\">\n                                                                    <tableHeaderCell key=\"headerCell\" lineBreakMode=\"truncatingTail\" borderStyle=\"border\" title=\"Description\">\n                                                                        <color key=\"textColor\" name=\"headerTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                                        <color key=\"backgroundColor\" name=\"headerColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                                    </tableHeaderCell>\n                                                                    <textFieldCell key=\"dataCell\" lineBreakMode=\"truncatingTail\" selectable=\"YES\" editable=\"YES\" title=\"Text Cell\" id=\"nIF-Tx-1jc\">\n                                                                        <font key=\"font\" metaFont=\"system\"/>\n                                                                        <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                                        <color key=\"backgroundColor\" name=\"controlBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                                    </textFieldCell>\n                                                                    <tableColumnResizingMask key=\"resizingMask\" resizeWithTable=\"YES\" userResizable=\"YES\"/>\n                                                                    <prototypeCellViews>\n                                                                        <tableCellView id=\"SHm-Un-XY1\">\n                                                                            <rect key=\"frame\" x=\"117\" y=\"1\" width=\"798\" height=\"17\"/>\n                                                                            <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                                                                            <subviews>\n                                                                                <textField verticalHuggingPriority=\"750\" horizontalCompressionResistancePriority=\"250\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"nW9-UM-Va8\">\n                                                                                    <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"798\" height=\"17\"/>\n                                                                                    <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" flexibleMinY=\"YES\"/>\n                                                                                    <textFieldCell key=\"cell\" lineBreakMode=\"truncatingTail\" selectable=\"YES\" editable=\"YES\" sendsActionOnEndEditing=\"YES\" title=\"Table View Cell\" id=\"2yV-Wg-Ryl\">\n                                                                                        <font key=\"font\" metaFont=\"system\"/>\n                                                                                        <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                                                        <color key=\"backgroundColor\" name=\"controlColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                                                    </textFieldCell>\n                                                                                    <connections>\n                                                                                        <action selector=\"tableViewDescField:\" target=\"-2\" id=\"8BU-hS-o9E\"/>\n                                                                                    </connections>\n                                                                                </textField>\n                                                                            </subviews>\n                                                                            <connections>\n                                                                                <outlet property=\"textField\" destination=\"nW9-UM-Va8\" id=\"QKg-MN-SQJ\"/>\n                                                                            </connections>\n                                                                        </tableCellView>\n                                                                    </prototypeCellViews>\n                                                                </tableColumn>\n                                                            </tableColumns>\n                                                            <connections>\n                                                                <outlet property=\"dataSource\" destination=\"-2\" id=\"NAl-in-SIY\"/>\n                                                                <outlet property=\"delegate\" destination=\"-2\" id=\"YTj-zj-q6U\"/>\n                                                            </connections>\n                                                        </tableView>\n                                                    </subviews>\n                                                </clipView>\n                                                <scroller key=\"horizontalScroller\" wantsLayer=\"YES\" verticalHuggingPriority=\"750\" horizontal=\"YES\" id=\"xLH-cc-oVs\">\n                                                    <rect key=\"frame\" x=\"1\" y=\"267\" width=\"856\" height=\"16\"/>\n                                                    <autoresizingMask key=\"autoresizingMask\"/>\n                                                </scroller>\n                                                <scroller key=\"verticalScroller\" hidden=\"YES\" wantsLayer=\"YES\" verticalHuggingPriority=\"750\" horizontal=\"NO\" id=\"sZr-dI-s2o\">\n                                                    <rect key=\"frame\" x=\"224\" y=\"17\" width=\"15\" height=\"102\"/>\n                                                    <autoresizingMask key=\"autoresizingMask\"/>\n                                                </scroller>\n                                                <tableHeaderView key=\"headerView\" wantsLayer=\"YES\" id=\"bx5-5m-J3h\">\n                                                    <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"907\" height=\"25\"/>\n                                                    <autoresizingMask key=\"autoresizingMask\"/>\n                                                </tableHeaderView>\n                                            </scrollView>\n                                            <button verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"KBT-QW-v1Y\">\n                                                <rect key=\"frame\" x=\"886\" y=\"515\" width=\"40\" height=\"32\"/>\n                                                <autoresizingMask key=\"autoresizingMask\" flexibleMinX=\"YES\" flexibleMinY=\"YES\"/>\n                                                <buttonCell key=\"cell\" type=\"push\" bezelStyle=\"rounded\" image=\"NSAddTemplate\" imagePosition=\"only\" alignment=\"center\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"xdH-8b-apY\">\n                                                    <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                                                    <font key=\"font\" metaFont=\"system\"/>\n                                                </buttonCell>\n                                                <connections>\n                                                    <action selector=\"addPoiClick:\" target=\"-2\" id=\"AVz-8M-YrB\"/>\n                                                </connections>\n                                            </button>\n                                            <button verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"EBI-tO-TJo\">\n                                                <rect key=\"frame\" x=\"886\" y=\"482\" width=\"40\" height=\"32\"/>\n                                                <autoresizingMask key=\"autoresizingMask\" flexibleMinX=\"YES\" flexibleMinY=\"YES\"/>\n                                                <buttonCell key=\"cell\" type=\"push\" bezelStyle=\"rounded\" image=\"NSRemoveTemplate\" imagePosition=\"only\" alignment=\"center\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"4VZ-Zm-k7I\">\n                                                    <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                                                    <font key=\"font\" metaFont=\"system\"/>\n                                                </buttonCell>\n                                                <connections>\n                                                    <action selector=\"removePoiClick:\" target=\"-2\" id=\"HHq-hF-Q0X\"/>\n                                                </connections>\n                                            </button>\n                                            <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"UlX-Eo-gXV\">\n                                                <rect key=\"frame\" x=\"446\" y=\"560\" width=\"34\" height=\"17\"/>\n                                                <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                                                <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"Time\" id=\"F2n-4W-a4s\">\n                                                    <font key=\"font\" metaFont=\"system\"/>\n                                                    <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                    <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                </textFieldCell>\n                                            </textField>\n                                            <popUpButton verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"6cg-pb-yCE\">\n                                                <rect key=\"frame\" x=\"488\" y=\"555\" width=\"77\" height=\"25\"/>\n                                                <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                                                <popUpButtonCell key=\"cell\" type=\"push\" title=\"Day\" bezelStyle=\"rounded\" alignment=\"left\" lineBreakMode=\"truncatingTail\" state=\"on\" borderStyle=\"borderAndBezel\" imageScaling=\"proportionallyDown\" inset=\"2\" selectedItem=\"AhW-Kq-A2V\" id=\"iDp-hW-rtu\">\n                                                    <behavior key=\"behavior\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                                                    <font key=\"font\" metaFont=\"menu\"/>\n                                                    <menu key=\"menu\" id=\"LVE-sF-JcU\">\n                                                        <items>\n                                                            <menuItem title=\"Day\" state=\"on\" id=\"AhW-Kq-A2V\"/>\n                                                            <menuItem title=\"Night\" id=\"scr-Ff-72j\"/>\n                                                        </items>\n                                                    </menu>\n                                                </popUpButtonCell>\n                                                <connections>\n                                                    <action selector=\"timePopUpChange:\" target=\"-2\" id=\"u0F-iB-vDf\"/>\n                                                </connections>\n                                            </popUpButton>\n                                            <customView fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Gip-M3-2o4\">\n                                                <rect key=\"frame\" x=\"129\" y=\"7\" width=\"683\" height=\"244\"/>\n                                                <autoresizingMask key=\"autoresizingMask\" flexibleMinX=\"YES\" flexibleMaxX=\"YES\"/>\n                                                <subviews>\n                                                    <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"hMF-uK-jzF\">\n                                                        <rect key=\"frame\" x=\"450\" y=\"194\" width=\"56\" height=\"17\"/>\n                                                        <autoresizingMask key=\"autoresizingMask\"/>\n                                                        <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"Duration\" id=\"LKV-Wr-NmT\">\n                                                            <font key=\"font\" metaFont=\"system\"/>\n                                                            <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                            <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                        </textFieldCell>\n                                                    </textField>\n                                                    <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"2Y8-Ra-MML\">\n                                                        <rect key=\"frame\" x=\"547\" y=\"194\" width=\"118\" height=\"17\"/>\n                                                        <autoresizingMask key=\"autoresizingMask\"/>\n                                                        <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"00:00\" id=\"qbW-H7-qPq\">\n                                                            <font key=\"font\" metaFont=\"system\"/>\n                                                            <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                            <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                        </textFieldCell>\n                                                    </textField>\n                                                    <avPlayerView fixedFrame=\"YES\" controlsStyle=\"none\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"PnC-8m-1v6\">\n                                                        <rect key=\"frame\" x=\"8\" y=\"6\" width=\"410\" height=\"231\"/>\n                                                        <autoresizingMask key=\"autoresizingMask\" flexibleMinX=\"YES\" flexibleMaxX=\"YES\"/>\n                                                    </avPlayerView>\n                                                    <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"T97-3N-PVi\">\n                                                        <rect key=\"frame\" x=\"450\" y=\"169\" width=\"68\" height=\"17\"/>\n                                                        <autoresizingMask key=\"autoresizingMask\"/>\n                                                        <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"Resolution\" id=\"7B0-6o-dm6\">\n                                                            <font key=\"font\" metaFont=\"system\"/>\n                                                            <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                            <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                        </textFieldCell>\n                                                    </textField>\n                                                    <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"HdI-qF-NRI\">\n                                                        <rect key=\"frame\" x=\"547\" y=\"169\" width=\"118\" height=\"17\"/>\n                                                        <autoresizingMask key=\"autoresizingMask\"/>\n                                                        <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"0x0\" id=\"8Ja-a9-MbP\">\n                                                            <font key=\"font\" metaFont=\"system\"/>\n                                                            <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                            <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                        </textFieldCell>\n                                                    </textField>\n                                                </subviews>\n                                            </customView>\n                                        </subviews>\n                                    </customView>\n                                </subviews>\n                            </customView>\n                        </subviews>\n                        <holdingPriorities>\n                            <real value=\"250\"/>\n                            <real value=\"50\"/>\n                        </holdingPriorities>\n                    </splitView>\n                </subviews>\n            </view>\n            <toolbar key=\"toolbar\" implicitIdentifier=\"9593C804-BE4E-42FF-8575-A97E57E2E0B7\" autosavesConfiguration=\"NO\" displayMode=\"iconAndLabel\" sizeMode=\"regular\" id=\"jEC-Lj-Bak\">\n                <allowedToolbarItems>\n                    <toolbarItem implicitItemIdentifier=\"49583858-EE1A-4634-AEB3-625DBF3AB8EC\" label=\"Custom View\" paletteLabel=\"Custom View\" sizingBehavior=\"auto\" id=\"X5T-B3-7hY\">\n                        <nil key=\"toolTip\"/>\n                        <textField key=\"view\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" id=\"BCy-1g-t5Q\">\n                            <rect key=\"frame\" x=\"0.0\" y=\"14\" width=\"137\" height=\"16\"/>\n                            <autoresizingMask key=\"autoresizingMask\"/>\n                            <textFieldCell key=\"cell\" lineBreakMode=\"truncatingTail\" alignment=\"center\" title=\"Manage Local Videos\" id=\"lfp-Sp-ytQ\">\n                                <font key=\"font\" usesAppearanceFont=\"YES\"/>\n                                <color key=\"textColor\" name=\"windowFrameTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                            </textFieldCell>\n                        </textField>\n                    </toolbarItem>\n                    <toolbarItem implicitItemIdentifier=\"0D35C4F1-03BE-48E7-9411-6BE416D5D215\" label=\"Custom View\" paletteLabel=\"Custom View\" image=\"NSAddTemplate\" sizingBehavior=\"auto\" id=\"MjR-Ti-gNi\">\n                        <nil key=\"toolTip\"/>\n                        <button key=\"view\" verticalHuggingPriority=\"750\" id=\"Mi6-Fv-bt4\">\n                            <rect key=\"frame\" x=\"0.0\" y=\"14\" width=\"127\" height=\"32\"/>\n                            <autoresizingMask key=\"autoresizingMask\"/>\n                            <buttonCell key=\"cell\" type=\"push\" title=\"Add Folder...\" bezelStyle=\"rounded\" image=\"NSAddTemplate\" imagePosition=\"left\" alignment=\"center\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"AvU-Xw-Nxc\">\n                                <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                                <font key=\"font\" metaFont=\"system\"/>\n                            </buttonCell>\n                            <connections>\n                                <action selector=\"addFolderButton:\" target=\"-2\" id=\"kkI-ir-HPa\"/>\n                            </connections>\n                        </button>\n                    </toolbarItem>\n                    <toolbarItem implicitItemIdentifier=\"NSToolbarFlexibleSpaceItem\" id=\"ZK4-sx-7Jg\"/>\n                </allowedToolbarItems>\n                <defaultToolbarItems>\n                    <toolbarItem reference=\"MjR-Ti-gNi\"/>\n                    <toolbarItem reference=\"ZK4-sx-7Jg\"/>\n                    <toolbarItem reference=\"X5T-B3-7hY\"/>\n                    <toolbarItem reference=\"ZK4-sx-7Jg\"/>\n                </defaultToolbarItems>\n            </toolbar>\n            <point key=\"canvasLocation\" x=\"100.5\" y=\"123\"/>\n        </window>\n        <viewController id=\"Qyu-39-RjD\" userLabel=\"Popover View Controller\">\n            <connections>\n                <outlet property=\"view\" destination=\"EXp-Os-dtD\" id=\"nba-IX-X21\"/>\n            </connections>\n        </viewController>\n        <popover behavior=\"semitransient\" id=\"6xN-bb-mFa\">\n            <connections>\n                <outlet property=\"contentViewController\" destination=\"Qyu-39-RjD\" id=\"UWg-en-1a0\"/>\n                <outlet property=\"delegate\" destination=\"-3\" id=\"CvE-Nq-7Sx\"/>\n            </connections>\n        </popover>\n        <customView id=\"EXp-Os-dtD\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"372\" height=\"236\"/>\n            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n            <subviews>\n                <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"eTx-Xc-mpB\">\n                    <rect key=\"frame\" x=\"18\" y=\"197\" width=\"103\" height=\"17\"/>\n                    <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                    <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"Time in seconds\" id=\"jXB-OB-x96\">\n                        <font key=\"font\" metaFont=\"system\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <textField verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"SpE-ag-aCO\">\n                    <rect key=\"frame\" x=\"135\" y=\"194\" width=\"96\" height=\"22\"/>\n                    <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                    <textFieldCell key=\"cell\" scrollable=\"YES\" lineBreakMode=\"clipping\" selectable=\"YES\" editable=\"YES\" sendsActionOnEndEditing=\"YES\" state=\"on\" borderStyle=\"bezel\" drawsBackground=\"YES\" id=\"Y8d-4d-DtZ\">\n                        <numberFormatter key=\"formatter\" formatterBehavior=\"custom10_4\" positiveFormat=\"0\" negativeFormat=\"0\" numberStyle=\"decimal\" allowsFloats=\"NO\" usesGroupingSeparator=\"NO\" groupingSize=\"0\" minimumIntegerDigits=\"0\" maximumIntegerDigits=\"2000000000\" id=\"Ixe-Fx-2fC\">\n                            <real key=\"minimum\" value=\"0.0\"/>\n                            <real key=\"maximum\" value=\"100\"/>\n                        </numberFormatter>\n                        <font key=\"font\" metaFont=\"system\"/>\n                        <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                    <connections>\n                        <action selector=\"timeTextChange:\" target=\"-2\" id=\"U2B-bB-bGx\"/>\n                        <binding destination=\"-2\" name=\"value\" keyPath=\"self.timeTextStepper.intValue\" id=\"V9h-dy-h1q\"/>\n                    </connections>\n                </textField>\n                <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"COF-GU-6D3\">\n                    <rect key=\"frame\" x=\"18\" y=\"145\" width=\"74\" height=\"17\"/>\n                    <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                    <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"Description\" id=\"epv-E0-LYu\">\n                        <font key=\"font\" metaFont=\"system\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"0in-qC-1Ge\">\n                    <rect key=\"frame\" x=\"32\" y=\"170\" width=\"312\" height=\"14\"/>\n                    <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                    <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"Leave at least a 10 second gap between points of interests\" id=\"fPg-id-tSS\">\n                        <font key=\"font\" metaFont=\"label\" size=\"11\"/>\n                        <color key=\"textColor\" name=\"secondaryLabelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <textField verticalHuggingPriority=\"750\" horizontalCompressionResistancePriority=\"250\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"3KO-Vs-fx0\">\n                    <rect key=\"frame\" x=\"20\" y=\"58\" width=\"332\" height=\"79\"/>\n                    <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                    <textFieldCell key=\"cell\" selectable=\"YES\" editable=\"YES\" sendsActionOnEndEditing=\"YES\" state=\"on\" borderStyle=\"bezel\" drawsBackground=\"YES\" id=\"Nhg-Qz-eB7\">\n                        <font key=\"font\" metaFont=\"system\"/>\n                        <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <button verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"j5W-EK-iiJ\">\n                    <rect key=\"frame\" x=\"105\" y=\"13\" width=\"164\" height=\"32\"/>\n                    <autoresizingMask key=\"autoresizingMask\" flexibleMaxY=\"YES\"/>\n                    <buttonCell key=\"cell\" type=\"push\" title=\"Add point of interest\" bezelStyle=\"rounded\" alignment=\"center\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"6nt-Ux-xor\">\n                        <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\"/>\n                        <string key=\"keyEquivalent\" base64-UTF8=\"YES\">\nDQ\n</string>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"addPoiValidate:\" target=\"-2\" id=\"18Z-aT-BQU\"/>\n                    </connections>\n                </button>\n                <stepper horizontalHuggingPriority=\"750\" verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Zrt-uf-nIH\">\n                    <rect key=\"frame\" x=\"236\" y=\"191\" width=\"19\" height=\"27\"/>\n                    <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                    <stepperCell key=\"cell\" continuous=\"YES\" alignment=\"left\" maxValue=\"100\" id=\"SZI-E5-Sxg\"/>\n                    <connections>\n                        <action selector=\"timeStepperChange:\" target=\"-2\" id=\"5r2-JP-RWu\"/>\n                        <binding destination=\"-2\" name=\"value\" keyPath=\"self.timeTextField.intValue\" id=\"Qsc-Li-7TT\"/>\n                    </connections>\n                </stepper>\n            </subviews>\n            <point key=\"canvasLocation\" x=\"-830\" y=\"47\"/>\n        </customView>\n        <userDefaultsController representsSharedInstance=\"YES\" id=\"FbY-zM-wGg\"/>\n        <menu id=\"bRP-nE-M4C\">\n            <items>\n                <menuItem title=\"Remove Folder and Videos\" id=\"hea-rl-zIh\">\n                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                    <connections>\n                        <action selector=\"menuRemoveFolderAndVideoClick:\" target=\"-2\" id=\"j9S-N5-FPG\"/>\n                    </connections>\n                </menuItem>\n                <menuItem title=\"Remove Video\" id=\"ytF-SB-6AJ\">\n                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                    <connections>\n                        <action selector=\"menuRemoveVideoClick:\" target=\"-2\" id=\"x2U-TG-Ecc\"/>\n                    </connections>\n                </menuItem>\n            </items>\n            <point key=\"canvasLocation\" x=\"-192\" y=\"570\"/>\n        </menu>\n        <window title=\"Add a local video folder\" allowsToolTipsWhenApplicationIsInactive=\"NO\" autorecalculatesKeyViewLoop=\"NO\" hidesOnDeactivate=\"YES\" releasedWhenClosed=\"NO\" visibleAtLaunch=\"NO\" frameAutosaveName=\"\" animationBehavior=\"default\" id=\"Atl-SY-oen\" customClass=\"NSPanel\">\n            <windowStyleMask key=\"styleMask\" titled=\"YES\" closable=\"YES\" utility=\"YES\"/>\n            <windowPositionMask key=\"initialPositionMask\" leftStrut=\"YES\" rightStrut=\"YES\" topStrut=\"YES\" bottomStrut=\"YES\"/>\n            <rect key=\"contentRect\" x=\"272\" y=\"172\" width=\"588\" height=\"131\"/>\n            <rect key=\"screenRect\" x=\"0.0\" y=\"0.0\" width=\"2560\" height=\"1415\"/>\n            <view key=\"contentView\" id=\"Qex-53-wYt\">\n                <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"588\" height=\"131\"/>\n                <autoresizingMask key=\"autoresizingMask\"/>\n                <subviews>\n                    <textField verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"npi-Wy-4IZ\">\n                        <rect key=\"frame\" x=\"20\" y=\"58\" width=\"548\" height=\"21\"/>\n                        <autoresizingMask key=\"autoresizingMask\"/>\n                        <textFieldCell key=\"cell\" controlSize=\"large\" scrollable=\"YES\" lineBreakMode=\"clipping\" selectable=\"YES\" editable=\"YES\" sendsActionOnEndEditing=\"YES\" borderStyle=\"bezel\" drawsBackground=\"YES\" id=\"WUt-Ke-j6t\">\n                            <font key=\"font\" metaFont=\"system\"/>\n                            <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                            <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        </textFieldCell>\n                    </textField>\n                    <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"LEA-Zt-ubF\">\n                        <rect key=\"frame\" x=\"20\" y=\"95\" width=\"394\" height=\"16\"/>\n                        <autoresizingMask key=\"autoresizingMask\"/>\n                        <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"Please type or copy the path of the folder you would like to add :\" id=\"gMX-To-sZw\">\n                            <font key=\"font\" metaFont=\"system\"/>\n                            <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                            <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        </textFieldCell>\n                    </textField>\n                    <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"UoE-IG-Sh3\">\n                        <rect key=\"frame\" x=\"20\" y=\"21\" width=\"307\" height=\"16\"/>\n                        <autoresizingMask key=\"autoresizingMask\"/>\n                        <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"Tip : You can also drag a folder inside the textfield\" id=\"l7O-bA-CcY\">\n                            <font key=\"font\" metaFont=\"system\"/>\n                            <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                            <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        </textFieldCell>\n                    </textField>\n                    <button verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"fQU-z6-oS0\">\n                        <rect key=\"frame\" x=\"471\" y=\"13\" width=\"103\" height=\"32\"/>\n                        <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                        <buttonCell key=\"cell\" type=\"push\" title=\"Add folder\" bezelStyle=\"rounded\" alignment=\"center\" controlSize=\"large\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"Rve-fz-dG7\">\n                            <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                            <font key=\"font\" metaFont=\"system\"/>\n                        </buttonCell>\n                        <connections>\n                            <action selector=\"addFolderCatalinaConfirm:\" target=\"-2\" id=\"wl2-r6-wYg\"/>\n                        </connections>\n                    </button>\n                </subviews>\n            </view>\n            <point key=\"canvasLocation\" x=\"1043\" y=\"-57.5\"/>\n        </window>\n    </objects>\n    <resources>\n        <image name=\"NSAddTemplate\" width=\"14\" height=\"13\"/>\n        <image name=\"NSRemoveTemplate\" width=\"14\" height=\"4\"/>\n    </resources>\n</document>\n"
  },
  {
    "path": "Resources/Old stuff/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>com.JohnCoates.Aerial</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>BNDL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>$(MARKETING_VERSION)</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleVersion</key>\n\t<string>$(CURRENT_PROJECT_VERSION)</string>\n\t<key>LSApplicationCategoryType</key>\n\t<string></string>\n\t<key>LSMinimumSystemVersion</key>\n\t<string>${MACOSX_DEPLOYMENT_TARGET}</string>\n\t<key>NSAppTransportSecurity</key>\n\t<dict>\n\t\t<key>NSAllowsArbitraryLoads</key>\n\t\t<true/>\n\t</dict>\n\t<key>NSLocationAlwaysUsageDescription</key>\n\t<string>Aerial uses location services to calculate Sunset and Sunrise times from your position</string>\n\t<key>NSLocationWhenInUseUsageDescription</key>\n\t<string>Aerial uses location services to calculate Sunset and Sunrise times from your position</string>\n\t<key>NSPrincipalClass</key>\n\t<string>AerialView</string>\n\t<key>SUFeedURL</key>\n\t<string>https://raw.githubusercontent.com/JohnCoates/Aerial/master/appcast.xml</string>\n\t<key>SUPublicEDKey</key>\n\t<string>fbiQGEFq55xl4bjwj2/SpIO4JMsKmEyhHEWlMMueyDY=</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "Tests/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>BNDL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>1.0</string>\n\t<key>CFBundleVersion</key>\n\t<string>1</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "Tests/PreferencesTests.swift",
    "content": "//\n//  PreferencesTests\n//  Aerial Tests\n//\n//  Created by John Coates on 9/22/16.\n//  Copyright © 2016 John Coates. All rights reserved.\n//\n/*\nimport XCTest\n@testable import AerialApp\n\nclass PreferencesTests: XCTestCase {\n\n    override func setUp() {\n        super.setUp()\n    }\n\n    override func tearDown() {\n        super.tearDown()\n    }\n\n    func testPreferenceSaving() {\n        let preferences = Preferences.sharedInstance\n        preferences.cacheAerials = false\n\n        let newPreferences = Preferences()\n        XCTAssertFalse(newPreferences.cacheAerials, \"Property write verified\")\n    }\n}\n*/\n"
  },
  {
    "path": "appcast.xml",
    "content": "<?xml version=\"1.0\" standalone=\"yes\"?><rss xmlns:sparkle=\"http://www.andymatuschak.org/xml-namespaces/sparkle\" version=\"2.0\">\n<channel>\n<title>Aerial</title>\n  \n  <item>\n<title>2.0.10</title>\n  <description>\n          <![CDATA[\n\n<p>If you want automatic updates, please install the Aerial Companion app, as Sparkle updates are now deprecated: https://aerialscreensaver.github.io</p>\n\n<p>What's new:</p>\n\n<ul><li>A lot! If you are upgrading from 1.9.X or older, check out our new site for more https://aerialscreensaver.github.io</li></ul>\n\n<p>Note: Big Sur Beta users, there's an issue currently regarding 3rd party screen savers, check this post on how to get back your settings and cache : #1036 This macOS bug affects not only all versions of Aerial, but all 3rd party screen savers.</p>\n\n<p>Note : this build works on both Intel and Apple Silicon</p>\n\n          ]]>\n  </description>\n<pubDate>jeu., 24 sep. 2020 21:00:00 +0100</pubDate>\n<sparkle:minimumSystemVersion>10.12</sparkle:minimumSystemVersion>\n<enclosure url=\"https://github.com/JohnCoates/Aerial/releases/download/v2.0.10/Aerial.saver.zip\" sparkle:version=\"2.0.10\" \nsparkle:edSignature=\"ik2c8p7tT24SA+tWKUma1yKP/vNrl6h3jBILpMCadzji/p/Doijf2rrwLG+3mpUx7q5OiHmUEzR6F3mTqNfGCQ==\" length=\"6632455\" type=\"application/octet-stream\"/>\n</item>\n  \n  <item>\n<title>1.9.1</title>\n  <description>\n          <![CDATA[\n<ul>\n<li>Add an option to hide battery indicator when it's full</li>\n<li>Fix the position of the weather info</li>\n<li>Fix a crash with some settings</li>\n</ul>\n          ]]>\n  </description>\n<pubDate>mer., 5 jui. 2020 15:00:00 +0100</pubDate>\n<sparkle:minimumSystemVersion>10.12</sparkle:minimumSystemVersion>\n<enclosure url=\"https://github.com/JohnCoates/Aerial/releases/download/v1.9.1/Aerial.saver.zip\" sparkle:version=\"1.9.1\" \nsparkle:edSignature=\"/u+5SrUpJCSVbTGMygyzGdbolaQ5t4IyFzf4sEZH1J/GDi+Eftu336HhRFmO9hP6zvDIDfRd8J1wGkLSkHQsDA==\" length=\"6425841\" type=\"application/octet-stream\"/>\n</item>\n<item>\n<title>1.9.0</title>\n  <description>\n          <![CDATA[\n<p>New features:</p>\n<ul>\n<li>Aerial can now display current weather conditions. This is done through Yahoo! Weather's API and can be configured in the Info tab.</li>\n<li>The textual battery indicator is now replaced with icons</li>\n<li>Add a 12/24h override to the Time info.</li>\n<li>New options to quickly select day/night videos</li>\n<li>Added an option to unmute sound in custom videos</li>\n<li>Add Italian translation, many thanks to @marguglio !</li>\n</ul>\n          ]]>\n  </description>\n<pubDate>mon., 25 mai. 2020 15:00:00 +0100</pubDate>\n<sparkle:minimumSystemVersion>10.12</sparkle:minimumSystemVersion>\n<enclosure url=\"https://github.com/JohnCoates/Aerial/releases/download/v1.9.0/Aerial.saver.zip\" sparkle:version=\"1.9.0\" \nsparkle:edSignature=\"TMRT0eUXNLVeq/za6lrRgxTzZd7FJazpzRu36xWXbMDK0xqF0BBOiKuIIy0sZ7fee9pVsmQt+mQ9u95WEwxzAg==\" length=\"6424628\" type=\"application/octet-stream\"/>\n</item>\n<item>\n<title>1.8.2</title>\n  <description>\n          <![CDATA[\n<p>New features:</p>\n<ul><li>Add a new Date Info </li>\n<li>Add a new Timer Info similar to Countdown, except it's a timer (say, 5 minutes)</li></ul>\n\n<p>Bug fixes:</p>\nFix text overlap bug \n<ul><li>Fix Location description bug when skipping videos on multiple monitors</li>\n<li>Fix and updates Countdown's display options</li></ul>\n\n<p>Updated translations:</p>\n<ul><li>Polish translations thanks to @Soruk !</li>\n<li>Chinese Simplified/Traditional translations thanks to @LinkeyLeo !</li>\n<li>Arabic translations thanks to @kachikulu !</li></ul>\n          ]]>\n  </description>\n<pubDate>mar., 24 mar. 2020 16:00:00 +0100</pubDate>\n<sparkle:minimumSystemVersion>10.12</sparkle:minimumSystemVersion>\n<enclosure url=\"https://github.com/JohnCoates/Aerial/releases/download/v1.8.2/Aerial.saver.zip\" sparkle:version=\"1.8.2\" \nsparkle:edSignature=\"P/P3lB7ZZu+q8KraIZFaOnz5p4QpqeYoW3hT12FcJ6xVzPZUAgv/3EkFExANOV+DvMRjixpiLLQ7nFUdOcRtCA==\" length=\"5991814\" type=\"application/octet-stream\"/>\n</item>\n<item>\n<title>1.8.1</title>\n  <description>\n          <![CDATA[\n<p>New features:</p>\n<ul><li>Changed \"Random\" to \"Random corner\" for location info randomness. Bottom/top center positions are now ignored here, but they can be used manually.</li>\n<li>Fix a preference panel crash if you disabled auto updates.</li>\n</ul>\n          ]]>\n  </description>\n<pubDate>mar., 3 mar. 2020 18:00:00 +0100</pubDate>\n<sparkle:minimumSystemVersion>10.12</sparkle:minimumSystemVersion>\n<enclosure url=\"https://github.com/JohnCoates/Aerial/releases/download/v1.8.1/Aerial.saver.zip\" sparkle:version=\"1.8.1\" \nsparkle:edSignature=\"9VAYxF1ZzzPAV4u7A4GnBPZBqqPfn75/PWfepc4QvwSjRUCm+ckj/o/MdKx7jTw1lmuBpaJ9ILSy75eHtJNqAA==\" length=\"5960639\" type=\"application/octet-stream\"/>\n</item>\n\n<item>\n<title>1.8.0</title>\n  <description>\n          <![CDATA[\n<p>New features:</p>\n<ul><li><b>New update system for macOS Catalina, you will now be notified and be able to download new versions. Aerial will still not be able to self update in Catalina, this is a sandboxing limitation that can't be worked around for the time being</b></li>\n<li>Add shadow controls</li>\n<li>Add translations for the new tvOS 13 videos in French</li>\n<li>Add a new Countdown information option</li></ul>\n<p>Bug fixes:</p>\n<ul><li>Fix the high sierra textfields workaround in new UI</li>\n<li>Fix battery detection in macs with no battery (oops)</li>\n<li>Fix localization that no longer worked in Catalina (come on...)</li></ul>\n\n<p>Misc:</p>\n<ul><li>Moved Sparkle from Cocoapods to a git submodule, updated Sparkle to 1.23</li>\n<li>Minimum macOS version is now 10.12</li></ul>\n          ]]>\n  </description>\n<pubDate>mar., 18 jan. 2020 18:00:00 +0100</pubDate>\n<sparkle:minimumSystemVersion>10.12</sparkle:minimumSystemVersion>\n<enclosure url=\"https://github.com/JohnCoates/Aerial/releases/download/v1.8.0/Aerial.saver.zip\" sparkle:version=\"1.8.0\" \nsparkle:edSignature=\"orTQ4SHPZDCcp+BLoffuL/1g+6fOpQPotDi7o3bAmQQ7mgpneRMyeOPbDNmM8eCs2VligzOlYlQOHdxju4kTBQ==\" length=\"5963341\" type=\"application/octet-stream\"/>\n</item>\n\n<item>\n<title>1.7.1</title>\n  <description>\n          <![CDATA[\n<b>Automatic updates are broken for the time being in Catalina. If you try to auto-update, it will look like it install correctly but the update process will silently fail because of new sandboxing restrictions. You will need to update manually for the time being, my apologies.</b>\n\n<ul><li>Brings back \"Allow right arrow to skip\" for macOS versions prior to Catalina. That feature still won't work on Catalina.</li>\n<li>Add seamless looping if you only have one video in your playlist.</li>\n<li>Fix \"new style\" settings that weren't saved immediately, causing a discrepancy if you didn't close the preferences panel before launching the screen saver (with a hot corner).</li></ul>\n          ]]>\n  </description>\n<pubDate>mar., 11 jan. 2020 16:00:00 +0100</pubDate>\n<sparkle:minimumSystemVersion>10.9</sparkle:minimumSystemVersion>\n<enclosure url=\"https://github.com/JohnCoates/Aerial/releases/download/v1.7.1/Aerial.saver.zip\" sparkle:version=\"1.7.1\" \nsparkle:edSignature=\"PEHtV0rb00reYVBETDHAj3MgE2ZxeCJA8xwnVAjWtjlmMkVmvgMCNouCYZwamqZ3Kmv26kZLwbl7UkjpeSAdDA==\" length=\"5968662\" type=\"application/octet-stream\"/>\n</item>    \n  \n<item>\n<title>1.7.0</title>\n  <description>\n          <![CDATA[\n          <b>Note : Catalina users, the auto-update process WILL still fail for the moment, please install this build manually. My apologies for the issue.</b>\n\nThis is a large rewrite, a few settings will be reset to default, including video format preference (4K, HDR), my apologies for this but those were needed to introduce some new features.\n\nNew features :\n\n<ul><li>New text rendering ! Aerial can now display information (such as location information, time, etc) on mulitple screens with new animations and better transitions. The settings for these are found in the new \"Info\" tab.</li>\n<li>Support for the 11 new Sea videos that were just released. If you do not see the videos after the update, please go to the \"Updates\" tab and press \"Check Now\" in the New videos section.</li>\n<li>New \"Battery\" Info can tell you your battery status (charging, %, etc)</li>\n<li>Infos can now be shown in more positions on screen (top center, bottom center, and screen center)</li>\n\nImportant fixes :\n\n<ul>\n<li>Fix the mini video issue on some systems using macOS Catalina, more info about this here.</li>\n</ul>\n          ]]>\n  </description>\n<pubDate>mer., 29 jan. 2020 21:00:00 +0100</pubDate>\n<sparkle:minimumSystemVersion>10.9</sparkle:minimumSystemVersion>\n<enclosure url=\"https://github.com/JohnCoates/Aerial/releases/download/v1.7.0/Aerial.saver.zip\" sparkle:version=\"1.7.0\" sparkle:shortVersionString=\"1.7.0\" sparkle:edSignature=\"hQN896uLYAxbqv4hRshK+bBOBrtjsH06kc1cJQwc8M7tvQrbmTkGxgoeAn1Kze4MPEk6pC8yf8H2sfJQplZ8Bw==\" length=\"5982268\" type=\"application/octet-stream\"/>\n</item>  \n  \n<item>\n<title>1.6.3</title>\n  <description>\n          <![CDATA[\n<ul>\n<li>Fix a bad crash with custom videos and HDR.</li>\n</ul>\n<p>If you are using or planning to upgrade to macOS Catalina, we very much suggest you check this issue about what to expect : https://github.com/JohnCoates/Aerial/issues/801</p>\n          ]]>\n  </description>\n<pubDate>jeu., 24 oct. 2019 14:00:00 +0100</pubDate>\n<sparkle:minimumSystemVersion>10.9</sparkle:minimumSystemVersion>\n<enclosure url=\"https://github.com/JohnCoates/Aerial/releases/download/v1.6.3/Aerial.saver.zip\" sparkle:version=\"1.6.3\" sparkle:shortVersionString=\"1.6.3\" sparkle:edSignature=\"z1UdHeGDFvMVXWlpu2y52UETr+i1CgcpA3VFsdZCaKfEGNeChv2IfcWIgrmPkLqGvhbchFMcnZlt1Akw1XucDQ==\" length=\"5997634\" type=\"application/octet-stream\"/>\n</item>  \n\n<item>\n<title>1.6.2</title>\n  <description>\n          <![CDATA[\n<ul><li>Fix a hang in Catalina when you can't/have a hard time resuming from screensaver.</li>\n<li>Fix Custom Videos in Catalina. You can also drop a folder there to automatically add it.</li></ul>\n<p>If you are using or planning to upgrade to macOS Catalina, we very much suggest you check this issue about what to expect : https://github.com/JohnCoates/Aerial/issues/801</p>\n          ]]>\n    </description>\n<pubDate>mar., 8 oct. 2019 17:00:00 +0100</pubDate>\n<sparkle:minimumSystemVersion>10.9</sparkle:minimumSystemVersion>\n<enclosure url=\"https://github.com/JohnCoates/Aerial/releases/download/v1.6.2/Aerial.saver.zip\" sparkle:version=\"1.6.2\" sparkle:shortVersionString=\"1.6.2\" sparkle:edSignature=\"av6bEU3Mi3ee06pKh+zR1fWwbLEAUzVMMuuyN2PNQ4j8aWE52pyjN7o9+j+jQJWoAvipj/dU4nsawDcd6bsZDA==\" length=\"5998259\" type=\"application/octet-stream\"/>\n</item>  \n\n<item>\n<title>1.6.1</title>\n  <description>\n          <![CDATA[\n<ul><li>Fixes the hang/crash happening when playing the next video on some systems with multiple monitor, since 1.5.0. Many thanks to @markusem !</li></ul>\n\n<p>If you are using or planning to upgrade to macOS Catalina, we very much suggest you check this issue about what to expect : https://github.com/JohnCoates/Aerial/issues/801</p>\n          ]]>\n    </description>\n<pubDate>mar., 1 oct. 2019 18:00:00 +0100</pubDate>\n<sparkle:minimumSystemVersion>10.9</sparkle:minimumSystemVersion>\n<enclosure url=\"https://github.com/JohnCoates/Aerial/releases/download/v1.6.1/Aerial.saver.zip\" sparkle:version=\"1.6.1\" sparkle:shortVersionString=\"1.6.1\" sparkle:edSignature=\"ScPasldYS9yGIUK48bUfEzxFLXI2pmAllAhVR1TRyJeQNeWV6xVknl4CWVVyyPqSW+G1EXmb8GOy5Goaj/qOBg==\" length=\"5992108\" type=\"application/octet-stream\"/>\n</item>  \n\n<item>\n<title>1.6.0a</title>\n  <description>\n          <![CDATA[\n<ul><li>This version includes support for the 15 new videos introduced in tvOS 13, including the 10 Sea videos and 5 new Space videos 🎉</li>\n<li>Adds HDR support for macOS Catalina 🎉</li>\n<li>Starting with this release, Aerial is properly signed and notarized 🎉</li>\n<li>Cache mechanism was changed to accommodate changes in macOS Catalina. We recommend you double check your cache settings after upgrading.</li>\n<li>Add Dutch translation by @sebastiaanspeck !</li>\n<li>Add Traditional Chinese and update Simplified Chinese translations by @LinkeyLeo !</li>\n<li>Add advanced mode for finely tuning the Spanned viewing mode in multi monitor configurations</li>\n<li>This version includes many fixes for various issues including with multi monitor setups and better support for older versions of macOS.</li>\n\n<p>If you are using or planning to upgrade to macOS Catalina, we very much suggest you check this issue about what to expect : https://github.com/JohnCoates/Aerial/issues/801</p>\n          ]]>\n    </description>\n<pubDate>jeu., 26 sept. 2019 19:23:00 +0100</pubDate>\n<sparkle:minimumSystemVersion>10.9</sparkle:minimumSystemVersion>\n<enclosure url=\"https://github.com/JohnCoates/Aerial/releases/download/v1.6.0a/Aerial.saver.zip\" sparkle:version=\"1.6.0a\" sparkle:shortVersionString=\"1.6.0a\" sparkle:edSignature=\"SkkVk6u5MEBamEhYVbJLCQKT8SUhOhEbiMJmKxfQSzZhaX53ckQfuO2eriOpwH73L9qmPmNmecaJCx16E8fcDw==\" length=\"5992428\" type=\"application/octet-stream\"/>\n</item>  \n  \n<item>\n<title>1.5.0</title>\n  <description>\n          <![CDATA[\n<p>1.5.0 brings some pretty big features to Aerial, most importantly:</p>\n\n<ul><li>- Completely rewritten multi monitor support. You can now enable and disable individual displays in the new Display tab.</li>\n<li>- New \"Spanned\" viewing mode. Selecting this mode will span an Aerial video on all your (selected) screens. You can even adjust margins.</li>\n<li>- Add your own videos to Aerial using the new Custom Videos features. You can add your own videos in the new video manager (found in the menu below the video list).</li></ul>\n\n<p>This version also includes many, many bugfixes! You can check the changelog for more information https://github.com/JohnCoates/Aerial/blob/master/Documentation/ChangeLog.md</p>\n          ]]>\n    </description>\n<pubDate>ven., 31 mai. 2019 11:30:00 +0100</pubDate>\n<sparkle:minimumSystemVersion>10.9</sparkle:minimumSystemVersion>\n<enclosure url=\"https://github.com/JohnCoates/Aerial/releases/download/v1.5.0/Aerial.saver.zip\" sparkle:version=\"1.5.0\" sparkle:shortVersionString=\"1.5.0\" sparkle:edSignature=\"Q3QYagdIRRrsRBst/W0FsR5w+J0dxIW4pHBjLw7J5aDB14v8nPsEKsJlj75eYXheCDWq/q+3brm7hD8Pypm7Ag==\" length=\"5946329\" type=\"application/octet-stream\"/>\n</item>\n  \n<item>\n<title>1.4.9</title>\n  <description>\n          <![CDATA[\n            <p>This is a bugfix for a crash for homebrew users and users who never starts the control panel. Sorry about that !</p>\n          ]]>\n    </description>\n<pubDate>mer., 1 mai. 2019 13:58:29 +0100</pubDate>\n<sparkle:minimumSystemVersion>10.9</sparkle:minimumSystemVersion>\n<enclosure url=\"https://github.com/JohnCoates/Aerial/releases/download/v1.4.9/Aerial.saver.zip\" sparkle:version=\"1.4.9\" sparkle:shortVersionString=\"1.4.9\"  sparkle:edSignature=\"C2SILYsMpGsvIVjlKvGmKxUhS2/95DrvD3xOzf2YAiZRh0gnHpNgDXt5OCMwzNd99iVinUAHq2nubqj1XqNPDA==\" length=\"5674907\" type=\"application/octet-stream\"/>\n</item>\n<item>\n<title>1.4.8</title>\n  <description>\n          <![CDATA[\n            <p>This new version includes many new features and enhancements:</p>\n            <ul>\n              <li>Support for January 25th video updates (finally)</li>\n              <li>Automatic updates support through Sparkle. You can manage how Aerial updates itself in the settings</li>\n              <li>Localization for community support in Arabic, Chinese Simplified, English, French, German, Hebrew, Polish and Spanish! Thanks to all the contributors. If you want to help, check our repository we very much welcome new contributions</li>\n              <li>You can now skip an Aerial with the right arrow key</li>\n              <li>You can now save your favorite videos sets to enable them quickly</li>\n            </ul>\n          ]]>\n    </description>\n<pubDate>mar., 30 avr. 2019 12:12:29 +0100</pubDate>\n<sparkle:minimumSystemVersion>10.9</sparkle:minimumSystemVersion>\n<enclosure url=\"https://github.com/JohnCoates/Aerial/releases/download/v1.4.8/Aerial.saver.zip\" sparkle:version=\"1.4.8\" sparkle:shortVersionString=\"1.4.8\"  sparkle:edSignature=\"5QFV0eqGRqCoZ8/TYbLXWOiVSifwNRUk4wuNFdjXJXpk/cRrceaTcs7SG168dawfOTpy9TOu283mb6WJGRQuDw==\" length=\"5674805\" type=\"application/octet-stream\"/>\n</item>\n</channel></rss>\n"
  },
  {
    "path": "beta-appcast.xml",
    "content": "<?xml version=\"1.0\" standalone=\"yes\"?><rss xmlns:sparkle=\"http://www.andymatuschak.org/xml-namespaces/sparkle\" version=\"2.0\">\n<channel>\n<title>Aerial</title>\n\n  <item>\n<title>2.0.10</title>\n  <description>\n          <![CDATA[\n\n<p>If you want automatic updates, please install the Aerial Companion app, as Sparkle updates are now deprecated: https://aerialscreensaver.github.io</p>\n\n<p>What's new:</p>\n\n<ul><li>A lot! If you are upgrading from 1.9.X or older, check out our new site for more https://aerialscreensaver.github.io</li></ul>\n\n<p>Note: Big Sur Beta users, there's an issue currently regarding 3rd party screen savers, check this post on how to get back your settings and cache : #1036 This macOS bug affects not only all versions of Aerial, but all 3rd party screen savers.</p>\n\n<p>Note : this build works on both Intel and Apple Silicon</p>\n\n          ]]>\n  </description>\n<pubDate>jeu., 24 sep. 2020 21:00:00 +0100</pubDate>\n<sparkle:minimumSystemVersion>10.12</sparkle:minimumSystemVersion>\n<enclosure url=\"https://github.com/JohnCoates/Aerial/releases/download/v2.0.10/Aerial.saver.zip\" sparkle:version=\"2.0.10\" \nsparkle:edSignature=\"ik2c8p7tT24SA+tWKUma1yKP/vNrl6h3jBILpMCadzji/p/Doijf2rrwLG+3mpUx7q5OiHmUEzR6F3mTqNfGCQ==\" length=\"6632455\" type=\"application/octet-stream\"/>\n</item>\n  \n  <item>\n<title>2.0.0beta4</title>\n  <description>\n          <![CDATA[\n\n<p>Please quit System Preferences before installing ! If you want auto updates, please give a try to Aerial's new installer/updater here : https://github.com/glouel/AerialUpdater</p>\n\n<p>This beta changes a lot of things (including the UI !), you will need to reconfigure your cache settings ! If you want more details on what's new, check this issue : https://github.com/JohnCoates/Aerial/issues/1006</p>\n\n\n<p>Fixes:</p>\n<ul><li>Weather</li></ul>\n\n<p>Note: Big Sur Beta 3 users, there's an issue currently with that beta of macOS regarding 3rd party screen savers, check this post on how to get back your settings and cache : https://github.com/JohnCoates/Aerial/issues/1006#issuecomment-664290581</p>\n\n<p>This macOS bug affects not only all versions of Aerial, but all 3rd party screen savers.</p>\n          ]]>\n  </description>\n<pubDate>ven., 3 aug. 2020 15:00:00 +0100</pubDate>\n<sparkle:minimumSystemVersion>10.12</sparkle:minimumSystemVersion>\n<enclosure url=\"https://github.com/JohnCoates/Aerial/releases/download/v2.0.0beta4/Aerial.saver.zip\" sparkle:version=\"2.0.0beta4\" \nsparkle:edSignature=\"z534eVjHm1k2eo+HPcvGC5va1o4NbpKWYPEFnAkV+/CvGBIISNmlJBbdzUwFDwHSaVqyZ5F6uibEXXMMBfiiBA==\" length=\"5336056\" type=\"application/octet-stream\"/>\n</item>\n  \n  <item>\n<title>1.9.1</title>\n  <description>\n          <![CDATA[\n<ul>\n<li>Add an option to hide battery indicator when it's full</li>\n<li>Fix the position of the weather info</li>\n<li>Fix a crash with some settings</li>\n</ul>\n          ]]>\n  </description>\n<pubDate>mer., 5 jui. 2020 15:00:00 +0100</pubDate>\n<sparkle:minimumSystemVersion>10.12</sparkle:minimumSystemVersion>\n<enclosure url=\"https://github.com/JohnCoates/Aerial/releases/download/v1.9.1/Aerial.saver.zip\" sparkle:version=\"1.9.1\" \nsparkle:edSignature=\"/u+5SrUpJCSVbTGMygyzGdbolaQ5t4IyFzf4sEZH1J/GDi+Eftu336HhRFmO9hP6zvDIDfRd8J1wGkLSkHQsDA==\" length=\"6425841\" type=\"application/octet-stream\"/>\n</item>\n<item>\n<title>1.9.1beta1</title>\n  <description>\n          <![CDATA[\n<ul>\n<li>Add an option to hide battery indicator when it's full</li>\n<li>Fix the position of the weather info</li>\n</ul>\n          ]]>\n  </description>\n<pubDate>mer., 27 mai. 2020 19:00:00 +0100</pubDate>\n<sparkle:minimumSystemVersion>10.12</sparkle:minimumSystemVersion>\n<enclosure url=\"https://github.com/JohnCoates/Aerial/releases/download/v1.9.1beta1/Aerial.saver.zip\" sparkle:version=\"1.9.1beta1\" \nsparkle:edSignature=\"wAo0HqOBz7dM7FTMdNee4SNJ6sxgC3e+7RWKVZc3WOhlCEzzuIjmnAfmb0j2vXdUzXyrW/fmOGADC9hCuWJMBw==\" length=\"6425229\" type=\"application/octet-stream\"/>\n</item>\n<item>\n<title>1.9.0</title>\n  <description>\n          <![CDATA[\n<p>New features:</p>\n<ul>\n<li>Aerial can now display current weather conditions. This is done through Yahoo! Weather's API and can be configured in the Info tab.</li>\n<li>The textual battery indicator is now replaced with icons</li>\n<li>Add a 12/24h override to the Time info.</li>\n<li>New options to quickly select day/night videos</li>\n<li>Added an option to unmute sound in custom videos</li>\n<li>Add Italian translation, many thanks to @marguglio !</li>\n</ul>\n          ]]>\n  </description>\n<pubDate>mon., 25 mai. 2020 15:00:00 +0100</pubDate>\n<sparkle:minimumSystemVersion>10.12</sparkle:minimumSystemVersion>\n<enclosure url=\"https://github.com/JohnCoates/Aerial/releases/download/v1.9.0/Aerial.saver.zip\" sparkle:version=\"1.9.0\" \nsparkle:edSignature=\"TMRT0eUXNLVeq/za6lrRgxTzZd7FJazpzRu36xWXbMDK0xqF0BBOiKuIIy0sZ7fee9pVsmQt+mQ9u95WEwxzAg==\" length=\"6424628\" type=\"application/octet-stream\"/>\n</item>\n<item>\n<title>1.8.3beta11</title>\n  <description>\n          <![CDATA[\n<ul>\n<li>Fix weather icons (for good!)</li>\n</ul>\n          ]]>\n  </description>\n<pubDate>sam., 2 mai. 2020 19:00:00 +0100</pubDate>\n<sparkle:minimumSystemVersion>10.12</sparkle:minimumSystemVersion>\n<enclosure url=\"https://github.com/JohnCoates/Aerial/releases/download/v1.8.3beta11/Aerial.saver.zip\" sparkle:version=\"1.8.3beta11\" \nsparkle:edSignature=\"eyL6lMTGKvs2tSt9CXvH4x03TNuFiXscnpKeqO2Bc8oFqtlEETksTm0PYlwsgbez2KewJL8yuaaIJiPxmYwVCw==\" length=\"6420492\" type=\"application/octet-stream\"/>\n</item>\n<item>\n<title>1.8.3beta9</title>\n  <description>\n          <![CDATA[\n<ul>\n<li>Weather icons should be sharper</li>\n<li>Night time calculation should now be correct</li>\n<li>Add a new battery icon indicator, set as default</li>\n</ul>\n          ]]>\n  </description>\n<pubDate>ven., 1 mai. 2020 19:00:00 +0100</pubDate>\n<sparkle:minimumSystemVersion>10.12</sparkle:minimumSystemVersion>\n<enclosure url=\"https://github.com/JohnCoates/Aerial/releases/download/v1.8.3beta9/Aerial.saver.zip\" sparkle:version=\"1.8.3beta9\" \nsparkle:edSignature=\"cYuAqOd4ufadts6AL+zE/t1sqjK/j0EXK+V59pB655SZvLDtM177gynyTIWbkBos1J1Q035kCXCeJTZzA1ulDg==\" length=\"6408710\" type=\"application/octet-stream\"/>\n</item>\n<item>\n<title>1.8.3beta8</title>\n  <description>\n          <![CDATA[\n<ul>\n<li>Flat icons should look much crispier now</li>\n<li>Potential fix for issues with dates</li>\n</ul>\n          ]]>\n  </description>\n<pubDate>mer., 29 avr. 2020 19:00:00 +0100</pubDate>\n<sparkle:minimumSystemVersion>10.12</sparkle:minimumSystemVersion>\n<enclosure url=\"https://github.com/JohnCoates/Aerial/releases/download/v1.8.3beta8/Aerial.saver.zip\" sparkle:version=\"1.8.3beta8\" \nsparkle:edSignature=\"uhbOJk0//OvsOg0vxvoDcuyd+vrhte5YHcPZK3YgDQ0ZzcrDK8YzPjYcmqic5cRgZ2gSVGa/9S2I17gFoLJEBg==\" length=\"6398568\" type=\"application/octet-stream\"/>\n</item>\n\n<item>\n<title>1.8.3beta7</title>\n  <description>\n          <![CDATA[\n<ul>\n<li>Fix sun icon being misnamed, causing a crash with sunny conditions (sorry!)</li>\n<li>Made the plist more human readable/editable for 3rd party toolsAdd a new icon set exported from SF Symbols for weather</li>\n</ul>\n          ]]>\n  </description>\n<pubDate>dim., 26 avr. 2020 19:00:00 +0100</pubDate>\n<sparkle:minimumSystemVersion>10.12</sparkle:minimumSystemVersion>\n<enclosure url=\"https://github.com/JohnCoates/Aerial/releases/download/v1.8.3beta7/Aerial.saver.zip\" sparkle:version=\"1.8.3beta7\" \nsparkle:edSignature=\"SkP8ugIRXY0Nubswx5X6lGPGh7Xr8rr6Cm6tTW9djDg/jh2ixbqckABTpTZ6vMouDGNk3XOT8GGQOfArYEAgBQ==\" length=\"6409464\" type=\"application/octet-stream\"/>\n</item>\n<item>\n<title>1.8.3beta6</title>\n  <description>\n          <![CDATA[\n<ul>\n<li>Add a new icon set exported from SF Symbols for weather</li>\n<li>Fixed night icons not showing, on SF Symbols and Yahoo's default icons</li>\n</ul>\n          ]]>\n  </description>\n<pubDate>ven., 24 mar. 2020 19:00:00 +0100</pubDate>\n<sparkle:minimumSystemVersion>10.12</sparkle:minimumSystemVersion>\n<enclosure url=\"https://github.com/JohnCoates/Aerial/releases/download/v1.8.3beta6/Aerial.saver.zip\" sparkle:version=\"1.8.3beta6\" \nsparkle:edSignature=\"z77zTXuSwWu+l3i4rzPckP43nJqriGe/mV5vFxNd7GqV8IIXhBbUOBKLbm8B2IHYme0ryatbWwf5roqh/IXxAA==\" length=\"6406005\" type=\"application/octet-stream\"/>\n</item>\n<item>\n<title>1.8.3beta4</title>\n  <description>\n          <![CDATA[\n<ul>\n<li>Fix (again) the beta update feed (sorry again !)</li>\n<li>Fix Location info not showing on some systems</li>\n</ul>\n          ]]>\n  </description>\n<pubDate>mar., 21 mar. 2020 19:00:00 +0100</pubDate>\n<sparkle:minimumSystemVersion>10.12</sparkle:minimumSystemVersion>\n<enclosure url=\"https://github.com/JohnCoates/Aerial/releases/download/v1.8.3beta4/Aerial.saver.zip\" sparkle:version=\"1.8.3beta4\" \nsparkle:edSignature=\"xYizghRQOVWsNrMUHEjdg3+NgiguME/I7aCv6wMf8Zfj/ff6LDopC7NyZZkt9nBcSUQhxHBbOjcsFY54dX16Bg==\" length=\"6221829\" type=\"application/octet-stream\"/>\n</item>\n\n  <item>\n<title>1.8.3beta3</title>\n  <description>\n          <![CDATA[\n<ul>\n<li>Add Fahrenheit on Weather, fix weather not working for some cities</li>\n<li>Add new options to easily check day or night videos</li>\n</ul>\n          ]]>\n  </description>\n<pubDate>lun., 20 mar. 2020 19:00:00 +0100</pubDate>\n<sparkle:minimumSystemVersion>10.12</sparkle:minimumSystemVersion>\n<enclosure url=\"https://github.com/JohnCoates/Aerial/releases/download/v1.8.3beta3/Aerial.saver.zip\" sparkle:version=\"1.8.3beta3\" \nsparkle:edSignature=\"WEgmoTt46XBitqayKWGiJi6IFtinTA2l6HmERfWE6D2IDTj7gVYRFCgrXH1mM770fKwvlJmjwrpcRS8yQqupCw==\" length=\"6221786\" type=\"application/octet-stream\"/>\n</item>\n<item>\n<title>1.8.3beta2</title>\n  <description>\n          <![CDATA[\n          <p>I mistakenly uploaded the wrong file for beta1, this is the correct new version, my apologies !</p>\n<p>New features:</p>\n<ul><li>Add a new Weather info. This is still super experimental and will be improved in next betas</li>\n<li>Add a 12/24h override</li>\n<li>Add Italian translation, many thanks to @marguglio !</li></ul>\n<p>Bug fixes:</p>\n<ul><li>Fix some locale bugs with Catalina</li>\n<li>Fix looping if you only had one video in your playlist</li></ul>\n          ]]>\n  </description>\n<pubDate>dim., 19 mar. 2020 19:00:00 +0100</pubDate>\n<sparkle:minimumSystemVersion>10.12</sparkle:minimumSystemVersion>\n<enclosure url=\"https://github.com/JohnCoates/Aerial/releases/download/v1.8.3beta2/Aerial.saver.zip\" sparkle:version=\"1.8.3beta2\" \nsparkle:edSignature=\"0cjBnfkUq6koMoIVatnNFOSsMtOHNUH31B/RbKNTFP+tPH1zrii1C7wUlgSCeshQVCU/D0yBCrsckjWYl0YJCw==\" length=\"6219582\" type=\"application/octet-stream\"/>\n</item>\n<item>\n<title>1.8.2</title>\n  <description>\n          <![CDATA[\n<p>New features:</p>\n<ul><li>Add a new Date Info </li>\n<li>Add a new Timer Info similar to Countdown, except it's a timer (say, 5 minutes)</li></ul>\n\n<p>Bug fixes:</p>\nFix text overlap bug \n<ul><li>Fix Location description bug when skipping videos on multiple monitors</li>\n<li>Fix and updates Countdown's display options</li></ul>\n\n<p>Updated translations:</p>\n<ul><li>Polish translations thanks to @Soruk !</li>\n<li>Chinese Simplified/Traditional translations thanks to @LinkeyLeo !</li>\n<li>Arabic translations thanks to @kachikulu !</li></ul>\n          ]]>\n  </description>\n<pubDate>mar., 24 mar. 2020 16:00:00 +0100</pubDate>\n<sparkle:minimumSystemVersion>10.12</sparkle:minimumSystemVersion>\n<enclosure url=\"https://github.com/JohnCoates/Aerial/releases/download/v1.8.2/Aerial.saver.zip\" sparkle:version=\"1.8.2\" \nsparkle:edSignature=\"P/P3lB7ZZu+q8KraIZFaOnz5p4QpqeYoW3hT12FcJ6xVzPZUAgv/3EkFExANOV+DvMRjixpiLLQ7nFUdOcRtCA==\" length=\"5991814\" type=\"application/octet-stream\"/>\n</item>\n<item>\n<title>1.8.2beta4</title>\n  <description>\n          <![CDATA[\n<ul><li>Fix the overlap bug for smaller screens/large fonts</li>\n<li>Add a Date info to show the current date</li></ul>\n          ]]>\n  </description>\n<pubDate>lun., 23 mar. 2020 19:00:00 +0100</pubDate>\n<sparkle:minimumSystemVersion>10.12</sparkle:minimumSystemVersion>\n<enclosure url=\"https://github.com/JohnCoates/Aerial/releases/download/v1.8.2beta4/Aerial.saver.zip\" sparkle:version=\"1.8.2beta4\" \nsparkle:edSignature=\"GOAdKfC/esCHVOZjNP2VTJBO3c5Z+O6m+Cp639QcJn56fRkYymQoMXpmwunCw6zebH6pKnKBRQ/wNmcLATGIBA==\" length=\"5987926\" type=\"application/octet-stream\"/>\n</item>    \n  \n<item>\n<title>1.8.2beta2</title>\n  <description>\n          <![CDATA[\n<p>New features:</p>\n<ul><li>Fix the seconds thing not working in Countdown info, removed year/months from the countdown info</li>\n<li>Add a new Timer Info similar to Countdown, except it's a timer (say, 5 minutes).</li>\n</ul>\n          ]]>\n  </description>\n<pubDate>jeu., 19 mar. 2020 18:00:00 +0100</pubDate>\n<sparkle:minimumSystemVersion>10.12</sparkle:minimumSystemVersion>\n<enclosure url=\"https://github.com/JohnCoates/Aerial/releases/download/v1.8.2beta2/Aerial.saver.zip\" sparkle:version=\"1.8.2beta2\" \nsparkle:edSignature=\"B5+J0DjZpAsSZjg1XU980ZAQxnLh/x1DTBsG/rHn9W/F45bhl56LCKfXtB+/hWzCCcI/JJhI+7VYHbHxqaDcCg==\" length=\"5977590\" type=\"application/octet-stream\"/>\n</item>\n  \n<item>\n<title>1.8.2beta1</title>\n  <description>\n          <![CDATA[\n<p>New features:</p>\n<ul><li>Add updated .pl translations</li>\n<li>Tentative fix for a description bug when skipping videos on multiple monitors.</li>\n</ul>\n          ]]>\n  </description>\n<pubDate>mar., 10 mar. 2020 18:00:00 +0100</pubDate>\n<sparkle:minimumSystemVersion>10.12</sparkle:minimumSystemVersion>\n<enclosure url=\"https://github.com/JohnCoates/Aerial/releases/download/v1.8.2beta1/Aerial.saver.zip\" sparkle:version=\"1.8.2beta1\" \nsparkle:edSignature=\"7eoSrfIP3HjIrS/pGQEMRFHxl0o6CIUrfLtvwkCaXhEHFRqXbedlHFNLSD92c4C+jAVZpFW8izMggMLrEOMWCw==\" length=\"5961990\" type=\"application/octet-stream\"/>\n</item>\n<item>\n<title>1.8.1</title>\n  <description>\n          <![CDATA[\n<p>New features:</p>\n<ul><li>Changed \"Random\" to \"Random corner\" for location info randomness. Bottom/top center positions are now ignored here, but they can be used manually.</li>\n<li>Fix a preference panel crash if you disabled auto updates.</li>\n</ul>\n          ]]>\n  </description>\n<pubDate>mar., 3 mar. 2020 18:00:00 +0100</pubDate>\n<sparkle:minimumSystemVersion>10.12</sparkle:minimumSystemVersion>\n<enclosure url=\"https://github.com/JohnCoates/Aerial/releases/download/v1.8.1/Aerial.saver.zip\" sparkle:version=\"1.8.1\" \nsparkle:edSignature=\"9VAYxF1ZzzPAV4u7A4GnBPZBqqPfn75/PWfepc4QvwSjRUCm+ckj/o/MdKx7jTw1lmuBpaJ9ILSy75eHtJNqAA==\" length=\"5960639\" type=\"application/octet-stream\"/>\n</item>\n\n<item>\n<title>1.8.1beta1</title>\n  <description>\n          <![CDATA[\n<p>Changed \"Random\" to \"Random corner\" for location info randomness. Bottom/top center positions are now ignored here, but they can be used manually.</p>\n          ]]>\n  </description>\n<pubDate>lun., 24 fev. 2020 19:00:00 +0100</pubDate>\n<sparkle:minimumSystemVersion>10.12</sparkle:minimumSystemVersion>\n<enclosure url=\"https://github.com/JohnCoates/Aerial/releases/download/v1.8.1beta1/Aerial.saver.zip\" sparkle:version=\"1.8.1beta1\" \nsparkle:edSignature=\"If2iGKSh/Cq23fhLuauufPpwLGZTrgjf4rtqpIuUkm7h1gKA7DeR1R2yW5OfnE9MJWvQYFKZyA7GYFcyhcizAQ==\" length=\"5960620\" type=\"application/octet-stream\"/>\n</item>    \n  \n<item>\n<title>1.8.0</title>\n  <description>\n          <![CDATA[\n<p>New features:</p>\n<ul><li><b>New update system for macOS Catalina, you will now be notified and be able to download new versions. Aerial will still not be able to self update in Catalina, this is a sandboxing limitation that can't be worked around for the time being</b></li>\n<li>Add shadow controls</li>\n<li>Add translations for the new tvOS 13 videos in French</li>\n<li>Add a new Countdown information option</li></ul>\n<p>Bug fixes:</p>\n<ul><li>Fix the high sierra textfields workaround in new UI</li>\n<li>Fix battery detection in macs with no battery (oops)</li>\n<li>Fix localization that no longer worked in Catalina (come on...)</li></ul>\n\n<p>Misc:</p>\n<ul><li>Moved Sparkle from Cocoapods to a git submodule, updated Sparkle to 1.23</li>\n<li>Minimum macOS version is now 10.12</li></ul>\n          ]]>\n  </description>\n<pubDate>mar., 18 jan. 2020 18:00:00 +0100</pubDate>\n<sparkle:minimumSystemVersion>10.12</sparkle:minimumSystemVersion>\n<enclosure url=\"https://github.com/JohnCoates/Aerial/releases/download/v1.8.0/Aerial.saver.zip\" sparkle:version=\"1.8.0\" \nsparkle:edSignature=\"orTQ4SHPZDCcp+BLoffuL/1g+6fOpQPotDi7o3bAmQQ7mgpneRMyeOPbDNmM8eCs2VligzOlYlQOHdxju4kTBQ==\" length=\"5963341\" type=\"application/octet-stream\"/>\n</item>    \n<item>\n<title>1.7.2beta3</title>\n  <description>\n          <![CDATA[\n<b>Automatic updates are broken for the time being in Catalina. If you try to auto-update, it will look like it install correctly but the update process will silently fail because of new sandboxing restrictions. You will need to update manually for the time being, my apologies.</b>\n\n<ul><li>More shadow options</li>\n<li>Fix High Sierra workarounds in new UI</li></ul>\n          ]]>\n  </description>\n<pubDate>sam., 15 jan. 2020 19:00:00 +0100</pubDate>\n<sparkle:minimumSystemVersion>10.9</sparkle:minimumSystemVersion>\n<enclosure url=\"https://github.com/JohnCoates/Aerial/releases/download/v1.7.2beta3/Aerial.saver.zip\" sparkle:version=\"1.7.2beta3\" \nsparkle:edSignature=\"RgtPcIcPMxur1jqgCDxsEmBddCQZq3vQHZMONrgw5WSTAt0cGz2EPjLghTsgFhIdgEDX5ZYDkGEFHrmH+BqyDA==\" length=\"6006059\" type=\"application/octet-stream\"/>\n</item>  \n\n<item>\n<title>1.7.2beta2</title>\n  <description>\n          <![CDATA[\n<b>Automatic updates are broken for the time being in Catalina. If you try to auto-update, it will look like it install correctly but the update process will silently fail because of new sandboxing restrictions. You will need to update manually for the time being, my apologies.</b>\n\n<ul><li>Fix text clipping issues with some fonts</li>\n<li>More UI cleanup, add a new Text settings option in Info tab</li></ul>\n          ]]>\n  </description>\n<pubDate>ven., 14 jan. 2020 19:00:00 +0100</pubDate>\n<sparkle:minimumSystemVersion>10.9</sparkle:minimumSystemVersion>\n<enclosure url=\"https://github.com/JohnCoates/Aerial/releases/download/v1.7.2beta2/Aerial.saver.zip\" sparkle:version=\"1.7.2beta2\" \nsparkle:edSignature=\"y0CqlWKJTJx2TEmJb6pobnVJvQUw+lUpQBNGePn+8M3/dFJXiwoYRWfZ6O55O1QO0gLASb6GM9ahwp+SdoQ/Bg==\" length=\"5999716\" type=\"application/octet-stream\"/>\n</item> \n\n<item>\n<title>1.7.2beta1</title>\n  <description>\n          <![CDATA[\n<b>Automatic updates are broken for the time being in Catalina. If you try to auto-update, it will look like it install correctly but the update process will silently fail because of new sandboxing restrictions. You will need to update manually for the time being, my apologies.</b>\n\n<ul><li>Add a new update check that shows a message at the top of the screen, when the screensaver is running, to let you know that a new version is available. This is still a work in progress and will be improved in the next beta. More info <a href=https://github.com/JohnCoates/Aerial/issues/909>here</a></li>\n<li>Add an option to change the shadow radius of the texts.</li>\n<li>Add a new Countdown info type.</li></ul>\n          ]]>\n  </description>\n<pubDate>jeu., 13 jan. 2020 16:00:00 +0100</pubDate>\n<sparkle:minimumSystemVersion>10.9</sparkle:minimumSystemVersion>\n<enclosure url=\"https://github.com/JohnCoates/Aerial/releases/download/v1.7.2beta1/Aerial.saver.zip\" sparkle:version=\"1.7.2beta1\" \nsparkle:edSignature=\"JfJ/8/eUs+cPHKCXjlWIU4MU/LlclYJB5nnh0ZwwuhhzWFqu26gOViyQc/0pMRSCi1S2RbUeX4pvwiIIbt38Bw==\" length=\"5996604\" type=\"application/octet-stream\"/>\n</item>  \n<item>\n<title>1.7.1</title>\n  <description>\n          <![CDATA[\n<b>Automatic updates are broken for the time being in Catalina. If you try to auto-update, it will look like it install correctly but the update process will silently fail because of new sandboxing restrictions. You will need to update manually for the time being, my apologies.</b>\n\n<ul><li>Brings back \"Allow right arrow to skip\" for macOS versions prior to Catalina. That feature still won't work on Catalina.</li>\n<li>Add seamless looping if you only have one video in your playlist.</li>\n<li>Fix \"new style\" settings that weren't saved immediately, causing a discrepancy if you didn't close the preferences panel before launching the screen saver (with a hot corner).</li></ul>\n          ]]>\n  </description>\n<pubDate>mar., 11 jan. 2020 16:00:00 +0100</pubDate>\n<sparkle:minimumSystemVersion>10.9</sparkle:minimumSystemVersion>\n<enclosure url=\"https://github.com/JohnCoates/Aerial/releases/download/v1.7.2beta1/Aerial.saver.zip\" sparkle:version=\"1.7.1\" \nsparkle:edSignature=\"PEHtV0rb00reYVBETDHAj3MgE2ZxeCJA8xwnVAjWtjlmMkVmvgMCNouCYZwamqZ3Kmv26kZLwbl7UkjpeSAdDA==\" length=\"5968662\" type=\"application/octet-stream\"/>\n</item>  \n<item>\n<title>1.7.1beta1</title>\n  <description>\n          <![CDATA[\n<b>Automatic updates are still broken for the time being in Catalina. If you try to update, it will look like it install correctly but the update process silently fails because of new sandboxing restrictions. You will need to update manually for the time being until a solution is found, my apologies.</b>\n\n<ul>\n<li>Brings back \"Allow right arrow to skip\" for macOS versions prior to Catalina. That feature still won't work on Catalina.</li>\n<li>Add seamless looping if you only have one video in your playlist</li>\n</ul>\n          ]]>\n  </description>\n<pubDate>lun., 03 jan. 2020 16:00:00 +0100</pubDate>\n<sparkle:minimumSystemVersion>10.9</sparkle:minimumSystemVersion>\n<enclosure url=\"https://github.com/JohnCoates/Aerial/releases/download/v1.7.1beta1/Aerial.saver.zip\" sparkle:version=\"1.7.1beta1\" sparkle:shortVersionString=\"1.7.1beta1\" sparkle:edSignature=\"2LEavx+JYtLJzZeHnoMM96XB0gtQL0uLdzq+3LtW3wyWpA5O5REig7JZy7WSatn1X3oWIL0eF4MjOSLnw1+DCw==\" length=\"5987274\" type=\"application/octet-stream\"/>\n</item>  \n  \n<item>\n<title>1.7.0</title>\n  <description>\n          <![CDATA[\n                    <b>Note : - Catalina users, the auto-update process WILL still fail for the moment, please install this build manually. My apologies for the issue.</b>\n\nThis is a large rewrite, a few settings will be reset to default, including video format preference (4K, HDR), my apologies for this but those were needed to introduce some new features.\n\nNew features :\n\n<ul><li>New text rendering ! Aerial can now display information (such as location information, time, etc) on mulitple screens with new animations and better transitions. The settings for these are found in the new \"Info\" tab.</li>\n<li>Support for the 11 new Sea videos that were just released. If you do not see the videos after the update, please go to the \"Updates\" tab and press \"Check Now\" in the New videos section.</li>\n<li>New \"Battery\" Info can tell you your battery status (charging, %, etc)</li>\n<li>Infos can now be shown in more positions on screen (top center, bottom center, and screen center)</li>\n\nImportant fixes :\n\n<ul>\n<li>Fix the mini video issue on some systems using macOS Catalina, more info about this here.</li>\n</ul>\n          ]]>\n  </description>\n<pubDate>mer., 29 jan. 2020 21:00:00 +0100</pubDate>\n<sparkle:minimumSystemVersion>10.9</sparkle:minimumSystemVersion>\n<enclosure url=\"https://github.com/JohnCoates/Aerial/releases/download/v1.7.0/Aerial.saver.zip\" sparkle:version=\"1.7.0\" sparkle:shortVersionString=\"1.7.0\" sparkle:edSignature=\"hQN896uLYAxbqv4hRshK+bBOBrtjsH06kc1cJQwc8M7tvQrbmTkGxgoeAn1Kze4MPEk6pC8yf8H2sfJQplZ8Bw==\" length=\"5982268\" type=\"application/octet-stream\"/>\n</item>  \n  \n<item>\n<title>1.6.3</title>\n  <description>\n          <![CDATA[\n<ul>\n<li>Fix a bad crash with custom videos and HDR.</li>\n</ul>\n<p>If you are using or planning to upgrade to macOS Catalina, we very much suggest you check this issue about what to expect : https://github.com/JohnCoates/Aerial/issues/801</p>\n          ]]>\n  </description>\n<pubDate>jeu., 24 oct. 2019 14:00:00 +0100</pubDate>\n<sparkle:minimumSystemVersion>10.9</sparkle:minimumSystemVersion>\n<enclosure url=\"https://github.com/JohnCoates/Aerial/releases/download/v1.6.3/Aerial.saver.zip\" sparkle:version=\"1.6.3\" sparkle:shortVersionString=\"1.6.3\" sparkle:edSignature=\"z1UdHeGDFvMVXWlpu2y52UETr+i1CgcpA3VFsdZCaKfEGNeChv2IfcWIgrmPkLqGvhbchFMcnZlt1Akw1XucDQ==\" length=\"5997634\" type=\"application/octet-stream\"/>\n</item>  \n\n<item>\n<title>1.6.2</title>\n  <description>\n          <![CDATA[\n<ul><li>Fix a hang in Catalina when you can't/have a hard time resuming from screensaver.</li>\n<li>Fix Custom Videos in Catalina. You can also drop a folder there to automatically add it.</li></ul>\n<p>If you are using or planning to upgrade to macOS Catalina, we very much suggest you check this issue about what to expect : https://github.com/JohnCoates/Aerial/issues/801</p>\n          ]]>\n    </description>\n<pubDate>mar., 8 oct. 2019 17:00:00 +0100</pubDate>\n<sparkle:minimumSystemVersion>10.9</sparkle:minimumSystemVersion>\n<enclosure url=\"https://github.com/JohnCoates/Aerial/releases/download/v1.6.2/Aerial.saver.zip\" sparkle:version=\"1.6.2\" sparkle:shortVersionString=\"1.6.2\" sparkle:edSignature=\"av6bEU3Mi3ee06pKh+zR1fWwbLEAUzVMMuuyN2PNQ4j8aWE52pyjN7o9+j+jQJWoAvipj/dU4nsawDcd6bsZDA==\" length=\"5998259\" type=\"application/octet-stream\"/>\n</item>  \n\n<item>\n<title>1.6.1</title>\n  <description>\n          <![CDATA[\n<ul><li>Fixes the hang/crash happening when playing the next video on some systems with multiple monitor, since 1.5.0. Many thanks to @markusem !</li></ul>\n\n<p>If you are using or planning to upgrade to macOS Catalina, we very much suggest you check this issue about what to expect : https://github.com/JohnCoates/Aerial/issues/801</p>\n          ]]>\n    </description>\n<pubDate>mar., 1 oct. 2019 14:00:00 +0100</pubDate>\n<sparkle:minimumSystemVersion>10.9</sparkle:minimumSystemVersion>\n<enclosure url=\"https://github.com/JohnCoates/Aerial/releases/download/v1.6.1/Aerial.saver.zip\" sparkle:version=\"1.6.1\" sparkle:shortVersionString=\"1.6.1\" sparkle:edSignature=\"ScPasldYS9yGIUK48bUfEzxFLXI2pmAllAhVR1TRyJeQNeWV6xVknl4CWVVyyPqSW+G1EXmb8GOy5Goaj/qOBg==\" length=\"5992108\" type=\"application/octet-stream\"/>\n</item>  \n\n<item>\n<title>1.6.0a</title>\n  <description>\n          <![CDATA[\n<ul><li>This version includes support for the 15 new videos introduced in tvOS 13, including the 10 Sea videos and 5 new Space videos 🎉</li>\n<li>Adds HDR support for macOS Catalina 🎉</li>\n<li>Starting with this release, Aerial is properly signed and notarized 🎉</li>\n<li>Cache mechanism was changed to accommodate changes in macOS Catalina. We recommend you double check your cache settings after upgrading.</li>\n<li>Add Dutch translation by @sebastiaanspeck !</li>\n<li>Add Traditional Chinese and update Simplified Chinese translations by @LinkeyLeo !</li>\n<li>Add advanced mode for finely tuning the Spanned viewing mode in multi monitor configurations</li>\n<li>This version includes many fixes for various issues including with multi monitor setups and better support for older versions of macOS.</li>\n\n<p>If you are using or planning to upgrade to macOS Catalina, we very much suggest you check this issue about what to expect : https://github.com/JohnCoates/Aerial/issues/801</p>\n          ]]>\n    </description>\n<pubDate>jeu., 26 sept. 2019 19:23:00 +0100</pubDate>\n<sparkle:minimumSystemVersion>10.9</sparkle:minimumSystemVersion>\n<enclosure url=\"https://github.com/JohnCoates/Aerial/releases/download/v1.6.0a/Aerial.saver.zip\" sparkle:version=\"1.6.0a\" sparkle:shortVersionString=\"1.6.0a\" sparkle:edSignature=\"SkkVk6u5MEBamEhYVbJLCQKT8SUhOhEbiMJmKxfQSzZhaX53ckQfuO2eriOpwH73L9qmPmNmecaJCx16E8fcDw==\" length=\"5992428\" type=\"application/octet-stream\"/>\n</item>  \n  \n<item>\n<title>1.5.1beta13</title>\n  <description>\n          <![CDATA[\n<p>This is the beta feed ! Aerial is properly signed and notarized 🎉</p>\n<ul>\n<li>Includes the new tvOS 13 videos, including sea and new space 🎉</li>\n<p>macOS 10.15 Catalina users, we suggest you first check this issue : https://github.com/JohnCoates/Aerial/issues/801</p>\n          ]]>\n    </description>\n<pubDate>mer., 25 sep. 2019 20:16:00 +0100</pubDate>\n<sparkle:minimumSystemVersion>10.9</sparkle:minimumSystemVersion>\n<enclosure url=\"https://github.com/JohnCoates/Aerial/releases/download/v1.5.1beta13/Aerial.saver.zip\" sparkle:version=\"1.5.1beta13\" sparkle:shortVersionString=\"1.5.1beta13\" sparkle:edSignature=\"4/bh8rb5Y24w+gnLg1eFum2Je2GxhAKCGr7KEtv8wYI6ffpBK8c6UaUdEmPbZYhGErPczMH1GrBaE8OFUoPpDw==\" length=\"5991026\" type=\"application/octet-stream\"/>\n</item> \n\n<item>\n<title>1.5.0</title>\n  <description>\n          <![CDATA[\n<p>1.5.0 brings some pretty big features to Aerial, most importantly:</p>\n\n<ul><li>- Completely rewritten multi monitor support. You can now enable and disable individual displays in the new Display tab.</li>\n<li>- New \"Spanned\" viewing mode. Selecting this mode will span an Aerial video on all your (selected) screens. You can even adjust margins.</li>\n<li>- Add your own videos to Aerial using the new Custom Videos features. You can add your own videos in the new video manager (found in the menu below the video list).</li></ul>\n\n<p>This version also includes many, many bugfixes! You can check the changelog for more information https://github.com/JohnCoates/Aerial/blob/master/Documentation/ChangeLog.md</p>\n          ]]>\n    </description>\n<pubDate>ven., 31 mai. 2019 11:30:00 +0100</pubDate>\n<sparkle:minimumSystemVersion>10.9</sparkle:minimumSystemVersion>\n<enclosure url=\"https://github.com/JohnCoates/Aerial/releases/download/v1.5.0/Aerial.saver.zip\" sparkle:version=\"1.5.0\" sparkle:shortVersionString=\"1.5.0\" sparkle:edSignature=\"Q3QYagdIRRrsRBst/W0FsR5w+J0dxIW4pHBjLw7J5aDB14v8nPsEKsJlj75eYXheCDWq/q+3brm7hD8Pypm7Ag==\" length=\"5946329\" type=\"application/octet-stream\"/>\n</item>  \n  \n<item>\n<title>1.4.99beta7</title>\n  <description>\n          <![CDATA[\n            <p>This is the beta feed!</p>\n<p>This version fixes many bugs in the new custom videos feature : </p>\n<ul><li>Videos will now play muted (!)</li>\n<li>Video manager now shows informations about resolution and duration of a video</li>\n<li>Fix stepper not working when adding a poi, fixed seeking when adding a poi</li>\n<li>4K custom videos now have the correct 4K badge in main UI</li>\n<li>customvideos.json is now pretty printed for easier manual editing</li>\n<li>Closing the custom video manager now properly reloads the video list in main UI</li></ul> \n<p>Find more information in this issue #786 !</p>\n<p>Please report any bug you find !</p>            \n          ]]>\n    </description>\n<pubDate>mer., 29 mai. 2019 13:20:29 +0100</pubDate>\n<sparkle:minimumSystemVersion>10.9</sparkle:minimumSystemVersion>\n<enclosure url=\"https://github.com/JohnCoates/Aerial/releases/download/v1.4.99beta7/Aerial.saver.zip\" sparkle:version=\"1.4.99beta7\" sparkle:shortVersionString=\"1.4.99beta7\"  sparkle:edSignature=\"yT16QQHx3Dyg1A3M2zriuzKc3eLxeHeFdug0lO8T2yLIBFXPoy64gP2thowESfqBWKqh1pentCrYycPZSJ+7Cg==\" length=\"5944919\" type=\"application/octet-stream\"/>\n</item>\n\n<item>\n<title>1.4.9</title>\n  <description>\n          <![CDATA[\n            <p>This is the beta feed.</p>\n            <p>This is a bugfix for a crash for homebrew users and users who never starts the control panel. Sorry about that !</p>\n          ]]>\n    </description>\n<pubDate>mer., 1 mai. 2019 13:58:29 +0100</pubDate>\n<sparkle:minimumSystemVersion>10.9</sparkle:minimumSystemVersion>\n<enclosure url=\"https://github.com/JohnCoates/Aerial/releases/download/v1.4.9/Aerial.saver.zip\" sparkle:version=\"1.4.9\" sparkle:shortVersionString=\"1.4.9\"  sparkle:edSignature=\"C2SILYsMpGsvIVjlKvGmKxUhS2/95DrvD3xOzf2YAiZRh0gnHpNgDXt5OCMwzNd99iVinUAHq2nubqj1XqNPDA==\" length=\"5674907\" type=\"application/octet-stream\"/>\n</item>\n\n<item>\n<title>1.4.8</title>\n  <description>\n          <![CDATA[\n            <p>This is the beta feed.</p>\n            <p>This new version includes many new features and enhancements:</p>\n            <ul>\n              <li>Support for January 25th video updates (finally)</li>\n              <li>Automatic updates support through Sparkle. You can manage how Aerial updates itself in the settings</li>\n              <li>Localization for community support in Arabic, Chinese Simplified, English, French, German, Hebrew, Polish and Spanish! Thanks to all the contributors. If you want to help, check our repository we very much welcome new contributions</li>\n              <li>You can now skip an Aerial with the right arrow key</li>\n              <li>You can now save your favorite videos sets to enable them quickly</li>\n            </ul>\n          ]]>\n    </description>\n<pubDate>mar., 30 avr. 2019 18:40:29 +0100</pubDate>\n<sparkle:minimumSystemVersion>10.9</sparkle:minimumSystemVersion>\n<enclosure url=\"https://github.com/JohnCoates/Aerial/releases/download/v1.4.8/Aerial.saver.zip\" sparkle:version=\"1.4.8\" sparkle:shortVersionString=\"1.4.8\"  sparkle:edSignature=\"5QFV0eqGRqCoZ8/TYbLXWOiVSifwNRUk4wuNFdjXJXpk/cRrceaTcs7SG168dawfOTpy9TOu283mb6WJGRQuDw==\" length=\"5674805\" type=\"application/octet-stream\"/>\n</item>\n</channel></rss>\n"
  },
  {
    "path": "issue_template.md",
    "content": "#### General troubleshooting tips\n\nBefore logging an issue please check that:\n- [ ] You have the latest version installed (There may be a beta version that fixes your issue), see here for the latest releases and bug fixes: https://github.com/JohnCoates/Aerial/releases\n- [ ] Your issue isn't already mentioned in our [issues](https://github.com/JohnCoates/Aerial/issues). You may find a workaround there or a similar request already made.\n- [ ] Your problem isn't mentioned in the [troubleshooting page](https://github.com/JohnCoates/Aerial/blob/master/Documentation/Troubleshooting.md).\n\nIf none of this fixes your issue, tell us about the problem you are experiencing or the feature you'd like to request.\n\n#### Required information\nIn order to help us sort your issue, we ask that you provide the following information:\n- [ ] Mac model: \n- [ ] macOS version: \n- [ ] Monitor setup: \n\nIf appropriate, please enable `Debug mode` and `Log to disk` in `Advanced` tab and replicate your bug, then attach the `AerialLog.txt` file (You can access this file through the Advanced tab).\n\n#### Description of issue / Feature request\n\n{{Replace this}}\n"
  },
  {
    "path": "lokalise.example.cfg",
    "content": "Token = \"YOUR_LOKALISE_TOKEN\"\nProject = \"526621525c59d35a304987.58424707\"\n"
  }
]