From 3e3a990f5e8833c1001c6d2a0613a2f4c6537b6f Mon Sep 17 00:00:00 2001 From: yumoqing Date: Mon, 22 Jun 2026 00:36:18 +0800 Subject: [PATCH] fix: replace Combine KVO with NSKeyValueObservation to prevent autorelease crash - Remove Combine import and cancellables - Use NSKeyValueObservation for timeControlStatus (controlled teardown) - Invalidate itemStatusObserver before replacing playerItem - Store endObserver token for proper removal - Add cleanup() method called on view disappear - Proper deinit with direct property cleanup (nonisolated-safe) --- Sources/Localization.swift | 53 +++++ Sources/MiniPlayerApp.swift | 3 + Sources/MiniPlayerIcon.swift | 105 +++++++++ Sources/PlayerBridge.swift | 41 +++- .../Resources/en.lproj/Localizable.strings | 31 +++ .../iOS/AppIcon.appiconset/Contents.json | 74 ++++++ .../iOS/AppIcon.appiconset/icon_1024.png | Bin 0 -> 15906 bytes .../iOS/AppIcon.appiconset/icon_120.png | Bin 0 -> 1406 bytes .../iOS/AppIcon.appiconset/icon_152.png | Bin 0 -> 1717 bytes .../iOS/AppIcon.appiconset/icon_167.png | Bin 0 -> 1849 bytes .../iOS/AppIcon.appiconset/icon_180.png | Bin 0 -> 2049 bytes .../iOS/AppIcon.appiconset/icon_40.png | Bin 0 -> 503 bytes .../iOS/AppIcon.appiconset/icon_58.png | Bin 0 -> 683 bytes .../iOS/AppIcon.appiconset/icon_60.png | Bin 0 -> 696 bytes .../iOS/AppIcon.appiconset/icon_80.png | Bin 0 -> 903 bytes .../iOS/AppIcon.appiconset/icon_87.png | Bin 0 -> 1039 bytes .../macOS/MiniPlayer.appiconset/Contents.json | 68 ++++++ .../macOS/MiniPlayer.appiconset/icon_128.png | Bin 0 -> 1542 bytes .../MiniPlayer.appiconset/icon_128@2x.png | Bin 0 -> 3498 bytes .../macOS/MiniPlayer.appiconset/icon_16.png | Bin 0 -> 271 bytes .../MiniPlayer.appiconset/icon_16@2x.png | Bin 0 -> 445 bytes .../macOS/MiniPlayer.appiconset/icon_256.png | Bin 0 -> 3498 bytes .../MiniPlayer.appiconset/icon_256@2x.png | Bin 0 -> 6485 bytes .../macOS/MiniPlayer.appiconset/icon_32.png | Bin 0 -> 445 bytes .../MiniPlayer.appiconset/icon_32@2x.png | Bin 0 -> 780 bytes .../macOS/MiniPlayer.appiconset/icon_512.png | Bin 0 -> 6485 bytes .../MiniPlayer.appiconset/icon_512@2x.png | Bin 0 -> 15906 bytes .../zh-Hans.lproj/Localizable.strings | 31 +++ generate_icons.py | 217 ++++++++++++++++++ 29 files changed, 612 insertions(+), 11 deletions(-) create mode 100644 Sources/Localization.swift create mode 100644 Sources/MiniPlayerIcon.swift create mode 100644 Sources/Resources/en.lproj/Localizable.strings create mode 100644 Sources/Resources/iOS/AppIcon.appiconset/Contents.json create mode 100644 Sources/Resources/iOS/AppIcon.appiconset/icon_1024.png create mode 100644 Sources/Resources/iOS/AppIcon.appiconset/icon_120.png create mode 100644 Sources/Resources/iOS/AppIcon.appiconset/icon_152.png create mode 100644 Sources/Resources/iOS/AppIcon.appiconset/icon_167.png create mode 100644 Sources/Resources/iOS/AppIcon.appiconset/icon_180.png create mode 100644 Sources/Resources/iOS/AppIcon.appiconset/icon_40.png create mode 100644 Sources/Resources/iOS/AppIcon.appiconset/icon_58.png create mode 100644 Sources/Resources/iOS/AppIcon.appiconset/icon_60.png create mode 100644 Sources/Resources/iOS/AppIcon.appiconset/icon_80.png create mode 100644 Sources/Resources/iOS/AppIcon.appiconset/icon_87.png create mode 100644 Sources/Resources/macOS/MiniPlayer.appiconset/Contents.json create mode 100644 Sources/Resources/macOS/MiniPlayer.appiconset/icon_128.png create mode 100644 Sources/Resources/macOS/MiniPlayer.appiconset/icon_128@2x.png create mode 100644 Sources/Resources/macOS/MiniPlayer.appiconset/icon_16.png create mode 100644 Sources/Resources/macOS/MiniPlayer.appiconset/icon_16@2x.png create mode 100644 Sources/Resources/macOS/MiniPlayer.appiconset/icon_256.png create mode 100644 Sources/Resources/macOS/MiniPlayer.appiconset/icon_256@2x.png create mode 100644 Sources/Resources/macOS/MiniPlayer.appiconset/icon_32.png create mode 100644 Sources/Resources/macOS/MiniPlayer.appiconset/icon_32@2x.png create mode 100644 Sources/Resources/macOS/MiniPlayer.appiconset/icon_512.png create mode 100644 Sources/Resources/macOS/MiniPlayer.appiconset/icon_512@2x.png create mode 100644 Sources/Resources/zh-Hans.lproj/Localizable.strings create mode 100644 generate_icons.py diff --git a/Sources/Localization.swift b/Sources/Localization.swift new file mode 100644 index 0000000..f17baa0 --- /dev/null +++ b/Sources/Localization.swift @@ -0,0 +1,53 @@ +import Foundation + +// MARK: - i18n 国际化 +enum L { + // 播放控制 + static let playPause = NSLocalizedString("play_pause", value: "Play/Pause", comment: "") + static let prev = NSLocalizedString("prev", value: "Previous", comment: "") + static let next = NSLocalizedString("next", value: "Next", comment: "") + static let fullscreen = NSLocalizedString("fullscreen", value: "Fullscreen", comment: "") + static let volUp = NSLocalizedString("vol_up", value: "Volume+", comment: "") + static let volDown = NSLocalizedString("vol_down", value: "Volume-", comment: "") + static let repeatMode = NSLocalizedString("repeat_mode", value: "Repeat Mode", comment: "") + static let openFile = NSLocalizedString("open_file", value: "Open File...", comment: "") + static let addURL = NSLocalizedString("add_url", value: "Add URL...", comment: "") + static let playback = NSLocalizedString("menu_playback", value: "Playback", comment: "") + static let file = NSLocalizedString("menu_file", value: "File", comment: "") + + // 播放列表 + static let playlist = NSLocalizedString("playlist", value: "Playlist", comment: "") + static let addFile = NSLocalizedString("add_file", value: "Add File", comment: "") + static let addURLBtn = NSLocalizedString("add_url_btn", value: "Add URL", comment: "") + static let itemsCount = NSLocalizedString("items_count", value: "items", comment: "") + static let noMedia = NSLocalizedString("no_media", value: "No media", comment: "") + + // URL弹窗 + static let addMediaURL = NSLocalizedString("add_media_url", value: "Add Media URL", comment: "") + static let cancel = NSLocalizedString("cancel", value: "Cancel", comment: "") + static let add = NSLocalizedString("add", value: "Add", comment: "") + + // 音轨 + static let selectTrack = NSLocalizedString("select_track", value: "Select Track", comment: "") + static let track = NSLocalizedString("track", value: "Track", comment: "") + static let audioTrack = NSLocalizedString("audio_track", value: "Audio Track", comment: "") + static let close = NSLocalizedString("close", value: "Close", comment: "") + + // 循环模式 + static let repeatNone = NSLocalizedString("repeat_none", value: "No Repeat", comment: "") + static let repeatSingle = NSLocalizedString("repeat_single", value: "Repeat One", comment: "") + static let repeatAll = NSLocalizedString("repeat_all", value: "Repeat All", comment: "") + + // Toast + static func nowPlaying(_ name: String) -> String { + String(format: NSLocalizedString("now_playing", value: "Now Playing: %@", comment: ""), name) + } + static func repeatModeLabel(_ mode: String) -> String { + String(format: NSLocalizedString("repeat_mode_label", value: "Repeat: %@", comment: ""), mode) + } + static let invalidURL = NSLocalizedString("invalid_url", value: "Invalid URL", comment: "") + + // 打开按钮 + static let open = NSLocalizedString("open", value: "Open", comment: "") + static let list = NSLocalizedString("list", value: "List", comment: "") +} diff --git a/Sources/MiniPlayerApp.swift b/Sources/MiniPlayerApp.swift index c8d2712..51f9a64 100644 --- a/Sources/MiniPlayerApp.swift +++ b/Sources/MiniPlayerApp.swift @@ -120,6 +120,9 @@ struct ContentView: View { .onReceive(NotificationCenter.default.publisher(for: .init("ExitFullscreen"))) { _ in bridge.toggleFullscreen() } + .onDisappear { + bridge.cleanup() + } } } diff --git a/Sources/MiniPlayerIcon.swift b/Sources/MiniPlayerIcon.swift new file mode 100644 index 0000000..89b32e5 --- /dev/null +++ b/Sources/MiniPlayerIcon.swift @@ -0,0 +1,105 @@ +import SwiftUI + +// MARK: - MiniPlayer 三色图标(播放键 + 三色圆环) +struct MiniPlayerIcon: View { + var body: some View { + GeometryReader { geo in + let size = min(geo.size.width, geo.size.height) + ZStack { + // 三色圆环 + RingArc(startAngle: -30, endAngle: 90) + .stroke(Color(red: 1.0, green: 0.23, blue: 0.19), lineWidth: size * 0.07) + .frame(width: size * 0.82, height: size * 0.82) + + RingArc(startAngle: 90, endAngle: 210) + .stroke(Color(red: 0.20, green: 0.78, blue: 0.35), lineWidth: size * 0.07) + .frame(width: size * 0.82, height: size * 0.82) + + RingArc(startAngle: 210, endAngle: 330) + .stroke(Color(red: 0.0, green: 0.48, blue: 1.0), lineWidth: size * 0.07) + .frame(width: size * 0.82, height: size * 0.82) + + // 三色播放三角 + TriColorPlay(size: size * 0.38) + .offset(x: size * 0.03) // 视觉居中偏移 + } + .frame(width: size, height: size) + } + } +} + +// MARK: - 圆弧段 +struct RingArc: Shape { + let startAngle: Double + let endAngle: Double + + func path(in rect: CGRect) -> Path { + var p = Path() + let center = CGPoint(x: rect.midX, y: rect.midY) + let radius = min(rect.width, rect.height) / 2 + p.addArc( + center: center, + radius: radius, + startAngle: .degrees(startAngle), + endAngle: .degrees(endAngle), + clockwise: false + ) + return p + } +} + +// MARK: - 三色播放三角(中心到三顶点分割) +struct TriColorPlay: View { + let size: CGFloat + + var body: some View { + Canvas { ctx, canvasSize in + let w = canvasSize.width + let h = canvasSize.height + + // 三角顶点(播放键朝右) + let top = CGPoint(x: w * 0.15, y: 0) + let bottom = CGPoint(x: w * 0.15, y: h) + let right = CGPoint(x: w, y: h * 0.5) + + // 重心 + let cx = (top.x + bottom.x + right.x) / 3 + let cy = (top.y + bottom.y + right.y) / 3 + let center = CGPoint(x: cx, y: cy) + + // 三色分区 + let red = Path { p in + p.move(to: center) + p.addLine(to: top) + p.addLine(to: right) + p.closeSubpath() + } + let green = Path { p in + p.move(to: center) + p.addLine(to: right) + p.addLine(to: bottom) + p.closeSubpath() + } + let blue = Path { p in + p.move(to: center) + p.addLine(to: bottom) + p.addLine(to: top) + p.closeSubpath() + } + + ctx.fill(red, with: .color(Color(red: 1.0, green: 0.23, blue: 0.19))) + ctx.fill(green, with: .color(Color(red: 0.20, green: 0.78, blue: 0.35))) + ctx.fill(blue, with: .color(Color(red: 0.0, green: 0.48, blue: 1.0))) + + // 分割线 + let lineW = max(0.5, w * 0.015) + for vertex in [top, bottom, right] { + var lp = Path() + lp.move(to: center) + lp.addLine(to: vertex) + ctx.stroke(lp, with: .color(.white.opacity(0.6)), lineWidth: lineW) + } + } + .frame(width: size, height: size) + } +} diff --git a/Sources/PlayerBridge.swift b/Sources/PlayerBridge.swift index 46fe77d..889aab6 100644 --- a/Sources/PlayerBridge.swift +++ b/Sources/PlayerBridge.swift @@ -61,9 +61,11 @@ final class PlayerBridge: ObservableObject { // MARK: - 内部状态 let player = AVPlayer() + var cancellables = Set() private var timeObserver: Any? private var itemStatusObserver: NSKeyValueObservation? - private var cancellables = Set() + private var playbackStatusObserver: NSKeyValueObservation? + private var endObserverToken: NSObjectProtocol? private var preferredTrackIndex: Int = 0 #if os(macOS) @@ -114,6 +116,10 @@ final class PlayerBridge: ObservableObject { currentIndex = index let item = queue[index] + // 先清除旧的 KVO,避免野指针 + itemStatusObserver?.invalidate() + itemStatusObserver = nil + let playerItem = AVPlayerItem(url: item.url) player.replaceCurrentItem(with: playerItem) player.play() @@ -136,7 +142,7 @@ final class PlayerBridge: ObservableObject { // MARK: - 播放结束 private func setupEndObserver() { - NotificationCenter.default.addObserver( + endObserverToken = NotificationCenter.default.addObserver( forName: .AVPlayerItemDidPlayToEndTime, object: nil, queue: .main ) { [weak self] _ in Task { @MainActor in self?.onPlaybackEnded() } @@ -330,8 +336,9 @@ final class PlayerBridge: ObservableObject { // MARK: - 播放列表窗口 @Published var showPlaylistSheet = false - @Published var lastInteraction = Date() - @Published var isInteracting = false + // 自动隐藏:非 @Published,避免 onHover 触发视图重建导致崩溃 + var lastInteraction = Date() + var isInteracting = false func recordInteraction() { lastInteraction = Date() } @@ -365,17 +372,29 @@ final class PlayerBridge: ObservableObject { // MARK: - 播放状态 private func setupPlaybackStatusObserver() { - player.publisher(for: \.timeControlStatus) - .receive(on: DispatchQueue.main) - .sink { [weak self] status in - self?.isPlaying = (status == .playing) - } - .store(in: &cancellables) + playbackStatusObserver = player.observe(\.timeControlStatus, options: [.new]) { [weak self] p, _ in + let playing = (p.timeControlStatus == .playing) + Task { @MainActor in self?.isPlaying = playing } + } + } + + /// 主动清理所有观察者,在 app 退出前调用 + func cleanup() { + if let obs = timeObserver { player.removeTimeObserver(obs); timeObserver = nil } + itemStatusObserver?.invalidate(); itemStatusObserver = nil + playbackStatusObserver?.invalidate(); playbackStatusObserver = nil + if let token = endObserverToken { NotificationCenter.default.removeObserver(token); endObserverToken = nil } + player.pause() + player.replaceCurrentItem(with: nil) } deinit { - if let observer = timeObserver { player.removeTimeObserver(observer) } + if let obs = timeObserver { player.removeTimeObserver(obs) } itemStatusObserver?.invalidate() + playbackStatusObserver?.invalidate() + if let token = endObserverToken { NotificationCenter.default.removeObserver(token) } + player.pause() + player.replaceCurrentItem(with: nil) } } diff --git a/Sources/Resources/en.lproj/Localizable.strings b/Sources/Resources/en.lproj/Localizable.strings new file mode 100644 index 0000000..d7ef7b0 --- /dev/null +++ b/Sources/Resources/en.lproj/Localizable.strings @@ -0,0 +1,31 @@ +"play_pause" = "Play/Pause"; +"prev" = "Previous"; +"next" = "Next"; +"fullscreen" = "Fullscreen"; +"vol_up" = "Volume+"; +"vol_down" = "Volume-"; +"repeat_mode" = "Repeat Mode"; +"open_file" = "Open File..."; +"add_url" = "Add URL..."; +"menu_playback" = "Playback"; +"menu_file" = "File"; +"playlist" = "Playlist"; +"add_file" = "📂 Add File"; +"add_url_btn" = "🔗 Add URL"; +"items_count" = "items"; +"no_media" = "No media"; +"add_media_url" = "Add Media URL"; +"cancel" = "Cancel"; +"add" = "Add"; +"select_track" = "Select Track"; +"track" = "Track"; +"audio_track" = "🎵 Audio Track"; +"close" = "Close"; +"repeat_none" = "No Repeat"; +"repeat_single" = "Repeat One"; +"repeat_all" = "Repeat All"; +"now_playing" = "Now Playing: %@"; +"repeat_mode_label" = "Repeat: %@"; +"invalid_url" = "Invalid URL"; +"open" = "Open"; +"list" = "List"; diff --git a/Sources/Resources/iOS/AppIcon.appiconset/Contents.json b/Sources/Resources/iOS/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..7b3bbd2 --- /dev/null +++ b/Sources/Resources/iOS/AppIcon.appiconset/Contents.json @@ -0,0 +1,74 @@ +{ + "images": [ + { + "filename": "icon_40.png", + "idiom": "iphone", + "scale": "2x", + "size": "20x20" + }, + { + "filename": "icon_60.png", + "idiom": "iphone", + "scale": "3x", + "size": "20x20" + }, + { + "filename": "icon_58.png", + "idiom": "iphone", + "scale": "2x", + "size": "29x29" + }, + { + "filename": "icon_87.png", + "idiom": "iphone", + "scale": "3x", + "size": "29x29" + }, + { + "filename": "icon_80.png", + "idiom": "iphone", + "scale": "2x", + "size": "40x40" + }, + { + "filename": "icon_120.png", + "idiom": "iphone", + "scale": "3x", + "size": "40x40" + }, + { + "filename": "icon_120.png", + "idiom": "iphone", + "scale": "2x", + "size": "60x60" + }, + { + "filename": "icon_180.png", + "idiom": "iphone", + "scale": "3x", + "size": "60x60" + }, + { + "filename": "icon_152.png", + "idiom": "ipad", + "scale": "2x", + "size": "76x76" + }, + { + "filename": "icon_167.png", + "idiom": "ipad", + "scale": "2x", + "size": "83.5x83.5" + }, + { + "filename": "icon_1024.png", + "idiom": "ios-marketing", + "scale": "1x", + "size": "1024x1024" + } + ], + "info": { + "author": "MiniPlayer", + "version": 1 + } +} \ No newline at end of file diff --git a/Sources/Resources/iOS/AppIcon.appiconset/icon_1024.png b/Sources/Resources/iOS/AppIcon.appiconset/icon_1024.png new file mode 100644 index 0000000000000000000000000000000000000000..0285f35a572db7ab48809cbea7a8730cbaf5a7c6 GIT binary patch literal 15906 zcmdse`Ck)P_y3tmA|Z$g2)GnUL{ShI+*(v5BZ??0ptwLwC9c?FE4Z}SDj5-rbptK# zOX7+PRZwfOwKC#{N(CS4(pRknu?T8Q5Y&hv^L-C}p6?&=;Rnsk+RaX@exsD$}Bb5&1;5UPF4x;JjnXqEG?P)A0~fVFwx>fbrZUC z5ngn*yH!Rh8^ibx9+cawSw>d>c{DA6{KL`4Fk}r)^QUpqb@=Tyk9G#oxbf2Oq4Vf> zydRC zk*Lj{EHBvlB^B(Hx-_OmB?Y?BKQC9YM8o1_DeD#VfwM@IllAn=&kM=&acD4+?t^5S zd4?>m)#(4SDWN>si|nh_N}{7Ty7Hay5NX3?ehO)5Dq+pTwAkzw>xXiQUbIo7Rgvvo zv7I#si2sohm-v#4K1oAr5|Lk~Jp1Gjjl=NAJHEa#F@Tnu z<)sl!PL5SQwa1IfRa5BbIOm-8tgcJ7_9$m@T0=2e?mD%C^DWWmY!%dR;+3GtERLa` z-R-iSO1m{=4drZf*M%xLwnVSlE2yu>DzV9!*|8+=ZI?}UZY|g}h}KSY)@)~WLDkx| zV=P%k9xOK`lHcJ$qrj>>O#kFydpZ!qUO7n0aW<#vZnphCYp7t0yUt6&1(oOvGA!y> z0W3c)ms0(Sb#ttWm#1^xsqBz^?I=c*X;phqs&hISnq{~CuJ^X2MDnjZh*65dX1UQ2 z7)~ie{Dcox{MAgOVaO_N=kV_2J<7S@w${sWznwv|UmM(VCcF#fm=r=-l(;I%*&!@k zM+SKyKh%TPgUrk@y=KiIO8ds$5ULO`&w?zAddy)Zy`I9B9i|;vW}oiOvfuq>d_(|K zJDDc-w97tHwsM{~$q?u#c&95!r@W*++H(GglGa{g4eoiOFf>D7vBsB*uBt3)D&9HM zXc@X+TNl-ZE<`w|^i>F#@MeoeZG9GBpH=SIOjY^;d((4c)sMRoIdyDd&aE8VM@E|t z#}CV?G}cYBIz5PRqd3NUG?SvK*0#9YnQJj}Zc!xP=s`{z$A0a8ttIXz)s1%!+V&+; z2u}Epcgs&G=|MSb2+9*HR$J5s+kB~|fbAT?1Yt|O!qF}CXU$H2Lg$l23w1Wxl_#H) z@P!wx4sOlbB{%X3eOYt=K>ld}wZjlTm$bSM!s)j|^0ZBXM4ix}Yl17K-C`}{qs0B~ zE@{p0ucxDzRR+C6=$L6Ng(j*CccY>H%fLvbq6* z{Ph6(LgVPJy`<$o@?dhlbGHlxM~A^+$jg=cmDJ}9r9lj(n3Sc+R-@jpps6Xp$DaC02Nh`;Y+hmvqjNN z!78h|5XWweS;?p6(vQoXbvf&-YR=>0cl^S>^iN8QdSF^9t2>_PxNdB**54{WA$ArP z<;6u7UiI7i7@MwyY5SsM@L-4}2Wu$>c|xRSIFm9>?X740-e0 zeyQTc%7OOcBTD{!K3z;=sBd>=#i;EDeTylp+^J7fG9yHK(J9cbSzeTTUA}ZJcxWOMM-<&;x#cELA5`dWSpc?`-~W+~ z4zu)^Om{NV`@D?bIU~1?4a=~+Yk~YZW8+{2h1|Z}H^MRGy{S(J56L=OEpG9p*TaVP zrv!$49$(s;q_kUpqM9ODrsJPAHI~%t7xuQDd3WYsfZmorsn_LtG5H=@cf?kD@(N1X zZY}R2Pk&H;OaA+1x*#q3=W8`(EOw9K#@+I$-mRKV`%B>3{9tJOL{8$u2r|-klOYz5B(UcoN=Z z8Xb*q>&|L#Hg>6c(<}~6rnD1(u;#mouh&@BRZWJq73!6?vWAc8LJZ3_xSM}XY@Wza zRhs6-ggU1cPR%Z2QY6{-vF0EJDIFg>w+cf)zQu29liS59{N3Wgnc|{cvhJV6SdwV}s%Prd6*vzE_0cP` zetVk7?$7q>cYUXVx-CyR0cU3Zv6p)vH;coQ>8EF>3Dj0}w^vTy>NNCGZ=3AITrqtz zJv<^epNL)UZnh^{Co){`-?e2$P=^OfZ7X}&7v(9>y+KmzUsw+ zl>?l`^2uz))njQA@7>QYP{)NtSe=er2WR|XJH{Q|zx3zS`3yI$#MmuEAM@wUhQ4{? zoOoHx@5gMcxjFHlHP&c+bA{sn^+m&gYO!-9^%>#WAIrvPW{P&X(HuBK_AJ2}D-b$w z_r}34bllCc1S+a_<*8w<`hD*Fx+pK=1wJUD7q?b)&<78ZjUy|#9GV#XE z%aeRE^jv;JWS-dQ&y>EHYVC?6A@{XEg~7<5=a!STT^82&5ksSt;xMI1g`wY-=Q*Op znwK+a?ZJnKs>?iSkej0h^PJsrP|cEV{K6UzMEg{rQD-r5?=i&ywxn?SSNs`dRP1C-1^=*t-PZgHWtQMT*}Hm9SPyXyK+ zpt#E{_3G%D1Izg7>2_;xxl?T{31do(Az)vLE8f<=v%8c+p4a}PG%a5I#5#_ z2@rT+v{`hI8sk{O`!6r@G#+2|FjI_!+Ps>$*rm~2|@EIya4*=RS-YInM}L_zJ` z9rrsrn9f&!;9n&;@r51~wANY-mswZ<2M4^u#0K%!;%yeSusOjwu6!AF#tirMw4d^` z%YxPq6+YZX)(|MVQMN=#!SFu3ph!x)-4N>Wva!ZwjBiactE-LOV5O9qcb0h!Ec;@3 zYn<Q<`VzOi!YiF?c8lRK3 zvkN^ytI=rXlFSdq5{yv5XRx1wrwA9(;Oa*UYgF{GyS*GoH)m%clML~`fo^gw5m#We zX>qc$Bxm|DfGnzNV<;r{X)ZMdFqYvni2n=X>a)a;)|RmJsJhwcgU|i*nc6~@e}fL5 z)opJ+M+bk#(oaDN8pl&N2U8d69F*-&7xRd(Qi@I3eM|G?J0hH^%AYu!363y->fb(r z#Vq%Al;f$!j{e1(pdaNiKUM5i(D%;b5_C)1Z5WQF`ZItQOt6_SN&d53TH?>tLE}s) z5xv2G$XMr~EO-9o1sVTErdWg3EHJ%c%c}R%(zy(^$D#lz1xctRMMPe-E|F1|z@hz4s%Ij6MuqpgS($J_MZAb=|LXEyDZ zoBJrJ;9EQn3}E>05mVMQ8$;kN&5mU^Bq_LX6-Bx^u44=8-~gsY((%a@^Nm$61#Rd3 znQO6Z%(pD1ZO7v<5J(0AOS7>r2rLGHc?!-`1^3Ev-QB^M+xZD`&~-7Cv&*XAh8{nF zz!WxTFUz0J6br%RQOPZJ=gT~Z$LFgc*hxiG7Psg(eP^V)QO-e|JSiSAZG=sWeaO$u zB?zT-9K-b~X%k%YA$jKrXYPF!EkFptKZ5c3j^&5!ab#orNw#QC9Fy}c%X?(D$;7h7 z-2j=yOVO}Ri{+$82j!hdJ9F(ofWzbGlUYu!qOc_`q9l_CVb0c&Kspdhnr+s$H))yf zmgSM;8%x||EL=gBJ3X61nk|*$Q*0Mua4wY>vO0*^1B*yK{28;4f~tdCtD-@D>=gC| zL_7uqxH;ZH#5@|jj%76)5zrEKjUml9m1652hm0alvk%Hu{5TKF)Y%&lQqkalo38m^ z(}F$!Z8|ufk*La5w9Wlrs-C&@E`W)f#E>&WS|Ku$O2;$8peXST&IYf<*EptN3(Naq z1?Z2=wHVrw#vGA9h;SAbsz@1y z2@QhDTA`vNsV!nK#8o=R*%};3^QRCOgYG$--RbcZ3R+W%VbV;VbjF{8_rL__iNwvH zPT8?+&}x=4B&Jlkq{(La(ZgDeh=6J80eRX6Pl|{IssO^|b5L#>he6?wQOssfy0V`v znkZ2#33+P(<1i{)o!ihn~C=D~i#7m-*cX)!pNioQu{Dc&nFAIL|6Uz#X9`vHNS%jV=!w5fN zB|eX4g#Hj0FRqLd8M;=;7GV!X_>%#lAsIsaXv0A=bcFax^PMMs6hH=&93 z4)mahe>IEmqoE}&lK&$goBw|li*D45pGg#~SPYyZXw0dC_eZ|HfaUXl4{t zg=tAL=hF~Qonb9Q|G!kV=prqu4w2_`jCF|k5m+_emP;unmQNhk3Rq`XJ_WRNYMW$72l&-~v9{v2ZB5PfU&UsW^2 zE_4*~zwIb!Q48L+BDbwVd|B*hu5Z$xde@QRij!&GW}m*a;08k4?k{9Ptv^4#Rqohd zxrH?|c_R1zNtT2s4Ufu=&Dj?q?7tBedI$2`o!rzt$ouu5a}?ZY75^Ah`=qs8eE0lk z#)F}ttjE8E!Xlz=QTm%x+RrcAqTOK7rqj}cfZOaU%a%%K;#Ydmnw_Gtyk6h)Vbb$7u)ZF#?I%p-&`+wA@j&_{(37`4if0lQf5=GdX7+Cq8+MAL|MV1g4kh~fd^>d6 zx(i)$9%&p9kE*dW>C^Sr~%lc$U$P(S7U$CSOJn!(n%&}D{EFZ8O^H?o@5gi_aj>I!E{(+ zZ-6Of!oSl1*+Y=c)-HkkV041X~LCP&CF|NzxQ*6Q%Af_k$$$fDfZz(g(kXv4F zdRx@ay0M`Uu@&WRnWabpUI3_$bp5dJUbk_gQwP!@upSe21YMRy5>z@r_o3)?^gJ7U zrX9fPtII-R{s)Opr^U8``Jx1wPC7gD=Kb>T{@HMV#$B;%4g8oue!~21H0H^>fKCdk z-vLQZZ(Fg{qITR^Os{49Pi$~3c>Nmk@jvw+Y}4QU$f{Iu?*E9!c@A~^?^d*NS+FUY z5(5r3#o(Zay*4Q>08pcc*xKfe$7e9oa!Fo}^NzMo-Uli`Xjm`7`y^v~bYl#J64>qE zfdxM>>hW>grfqX$f<&jW#~oopGB)4!6j#2l2VFWZs#7*Z&0uCWVaZn%H)EIZW3fq+ ziRvOi?4!NdcaV79XogF}_J|$&A&yEvfWePs@KSgI;tJm9DSUvv88TtN_ih}JnaTgo zl$!*{VzB5mzpmvBG%7T1O;@@TKqO4#cb5%=Kc?VfKvRxmsYd^Whl4j^RjIf!4EYBJ z`j6!cKtBw}YkOrk{>^f=lq`VW^Ax^7dkG=dVOM0p3P^|N>nc}Zx5Uq|_qBwA=e3g< zZXD>JIIk)&#cItX8W_nFqJ@9;5$2;m3_Q_E5Z~uZ^f-p(H3}ZvE@e9X?9cL_C&*I# z`ud{%LxUn{+Z&_|hGQAiay^CEe1;6J(wFKaCL6dPe;$6(oSA+rm!7c%Ny^l$AIsjW`m^xH%Y7}0Vxf`^43VxVy4rQotszzX12u2a=Oo) z4T=>1WYP^D!1i=kaGIH<%-Q2^Nm)nyp8WIR7$MS0Hos<+JJK9@@SjeVap1EC+*lm? zoXwuXSL;Y8!@O1CcEemnK_*822YX(q^W@zPT^eADo&%+}DTsfVpjdmgE9ra`pS8zC zgCXU`kRreq{x8hqsG!pI&x_*ZGv(vp+fnd3PY!_unK6x7`SciDy8?g-dEZd!dWI8q z3m~s17os0*@j}7{EeT1VBb?awlI6_4GnmDY$oxiMZo0%v`;%;Do)U>3sXK-lfbPgB zA%hgiPeoV$Qyk(HO(1WF;E#@h>j+7lovX+JSl0RKdWs*<6y%slezd%tz4!P-;>+*A zgQt|B8O)~`r|rb%Tl#Pi2A!4!C7({qaE?kPkK#lell!=pXiOd%oQnxjk|M@5lnT}) zvIb8ul#geO!>p5n`A(+3i(CHKK21E##Fb6sXM(Xu>HSZCg9Y|Y@id2E z2FO{FfeGXBE7m6o&T|RQcAK<4;}CXp*V!Ry1=u1O2=fd-9#Y;e4zs zH{>LH7SO)rWKvw2ioY+3p$9aF&Nq;MjnO(oe-aZ1PX@ff*L2zAcs=i`F`iBrvX%^N zLBG(-dlDs0x>pWje&h{U{#d93xrtQ%y#$591qk`SP_c4|v=!?T6c!cO&Xzg_!416m z@rQIydT2MD9?pUdlkA(aRK@>-2_;Bf`of9flNq{j1P^9=UtRg>cF0R%F6c)qq`b<1(Mg9cKqL=E8qUE?|($d^U4*x(rgh*6+w7;y<+uuFY z%cuZ}n~ASY;;rHpb#?mmxYpie`Jvd}U`$QgmFuV}cAP?vk_E34Q4j!+OF6ynyI_K5jF4AanL!IeLa2hgfbIc7{0Z;Z9VydY0R1-Vvr zP?p4fO|z*l06C~!idox9+`J0tp>*!nH9giJ0B&;cr8GiGv#B)GC`Dcq8}o|AyZTRP zL09`4W6|GvlDD}w03bEb?s0V7SfSQrgD#B*Lj&W%(BdfZ+c2vW%m>l8SWI6KZQB9^ z(_d%DOIY9q8PS$Otx0~>TAda;j@}2)FQqj@>TV}c-%@Fng=s+Rx;?_L8^NtfUe#K& z7ut@yQtlXtBv;IL;CV~a8RG_Do9s8~1ofOK4qInYSFDD3@4a<-9c>h!Khv{hjeMHa zajgY>+bizkbewYZI6DVaok11J9Ww$Ol0Us_+|bh|YyJyT?D^!X@dW^f=J{x~YNul` zGM9o2T5*#zkjsMLG`W?=*FYfCvL)GiAcvf?QKIss*%Sf9Nb)v#gZ+gz8&iL9)02+0 zR91=4Ou<42h~P~|u~mJ(wfSxK3GrXu!A%r@hr|#Q3hc$R4F5~HW?v6pg`=?im3F@$ zGF-fFk7Ef$Eg;8E8ora5y3wi@{H2H7PU0)%!w~pF2M%t1ifp44JVUzy*Yo~$1nu|- zk~m>}M#ZTuAg+$PI2SQAgYF#mGL=pj1%vYCK~+j~z7kAjOrgmT~GM;ty#zv_iV+ zBIH;V2GiF#foLuky9cc8bZL_Y=TwUJzOSKyFp&E(@y9k5oOl3zea z#9>&JskLBlxtosM(k^L(R(GP)yI8}(-mdg2xV8N1mjjXDWm87Zz+|?8sh=b}#{u5P z&a9JS@zvn=f%KuN18r;a<;;Wh?>eovs`G0V{21xL%XT=fV+RQzcoCBp%-(O5* z9$Q^#AT*|U7#HQzF3jo`gcEW>u993 z4UkLwCrM&006|Ntir0md(v#UO#owIQbD`;s4%v`dX;_{6N(VRnAF<=N*o?yJJ&y7@ z-JRNWgCM(LTLg@iuARoTdM|IRii1$RFS9z0I)n;$I<&V&8u_m-P>`2`_JbErkBrCG zPUJ2jSnsE_7~4PpfOcFTf!_6)`wr9p zcsJ+(VYU55)g1IdW}j%r4u@Xq5tqQ|dg`5&IonOIWIqiSdrRKr1?1pDqgokVe+9?+ z?4#0a$8g5ltUwMgDT~i?(vGP>$ZPRn_O)!6j=J10^L~E6z1zz}mjI$?R0j!oB}9T2uhp zyvpi=)k);t_~+wy3jWSRF*};!RF7ah?lm?iLI;2IPMo_R24?Rj{kx}EwA7}>SF{YU z$tcN-oYT_Y-5g4W%>I?eB}RT&nOMA7)H^}j`H%UeJtaU}aqr!Y7S|Zbf?^7HpJx{r zyOO1~L0Q$2nh>SWbC|LMiO$Agv^pp9k%qePss0@xdiuJE<%XYRs0XsdogB>UAhCB3 zl!ExQP)n5fXOol8_l>wjI)ZGhgQbIUl(Qw7xU5Pelyk2p{u_BwKAoG zU9ZI%S6+-#qq;#5~86OsmVBWuN~BGH61MaRO2wRW;Id>uGBWt_~Mqt z)rj*GWW3LOlf%V9Bf-zc?ZgV6QSTT&vM>2xSJ9`tm$eLlt*C7_twVKBT8v`&4(PI4 z2U$nH5ue9U%oa~-9{5a}fdzJZ+HxnN@AE{jsQ@FqXieH$h4s8M_1G!iKS1Wb_sP8J zPM(PF33D9L^Hluod~9Ij*p@wV{Eav_^ z?6H6o1^~ zcmp&2?+1hQa#y7huv0}&GG12fert?Yk!|Cb&|kmRG;1$TrXf;S8ab@B0ZwEmEDJpY z%vcpmL*`2#ehF@EfXj1A^820u*nBjFgb}&;u-sX+qOxiU&LDB>TG1bwG3;u71!^*u zsYoJZ28Iq_UvQl+wFfc>oYQ{uXX#6?JaG>o$qrHv8+xo%k>ireGTaZu5=z8nQQ~=k z4*yPL#dUm;8m6^jtET(d+?Wdwe6|gJMNE&?MwjIX-F*%LOo@xOWuYo34Nxh#hWi3& zq+m53gyE>XfM+x#o&t+Iq-T0(G%1b8pc z{2xUtLf3av!+lSIwC9N-u*Xg@`1+!^{W5^=kTNVb-CNvJ?xUjMwG#I=QoReH`PtIS zB*W1I5dU)k^UoRddVqAu$`XA!__`#m&l_hkB}75dh3tc|&Io(=T8lSU8uuN>r?y=a z@++#0B&lM{EQ0s!h8!+ZA!K>4T8ls<2)G>53`EtUTa?&E@^{*B`_9)?h7ssy9$YE@ zy~i;a37Y*#Q3Swm-qe<$7z+&A6e`xak1gK`_pRm*}O$34%>R;x2YgAekh8hcxE6VpA#E8QqMb@Hdr3?AL@7rE z@yylPM@u;(B(#u#r7^wi4Uoz2h!gUpToT^&v^St)1|hloWH7Q>DFSHX{iOA)yIHRX z)EGC`xgZ-OX;xK=D>IGLr@-%r91I8t7EeK>;whv{kBVxeK2OX)LWW^}|Gw#kH`OMk z2S~N;YE3@9mR58=5<8|!;{hq*=5Ekqz9~K1nj+u!-=;DDZMq5BO;8ni|2a}`#kXUW>WS{#Oe23sy%TDp;$#-kG$E^a!N$71Acjl=X5p%OYA zk*DoL{|8|<<34NjQYixoX*~3`k46Tv1nrKQP>iIxmq_bEP+}is+V5CUCLcrXBw$y1C zsZtpERZ#p&c;VC#=5mXl%g8&>ELe7G>(g>*nVn$n~1Jz-q2wT>VC^YZz-%f4C64fh>MK6oh zLBGgjE+Dsx64zM_%}^d}ikDH$Mynp@qzHcR2mVYgHgL=uys@f(Z2f0+_y1M8f9f82 zKSqEauoQn|E#Hi)_X%^8P!_^zJ|5l3a_^UjT}$)}4-&sImy#j=(lDuBBg**7`XYwS$E;9OW9(L~m8wSf z={B4^yp}O2E*bk(n>xDs+uI-f2#!*X0&TCH*8apa(;_K&PyY^afGB1-c45>Dbtkzz`Fzu$W`FV0Oc>MbY z%yrOZUNh$~2K6O%+{1=n#ilAp)fT;8sL1-xLSiNkgoFTkWAy+t1Pjn<)z`NGR^aMcT_qE`bCtY6aD1~+m4LTh;Xhy z@U+fVSt|Yqxv@{MXM1tL1-XXp=)Yw01G-{c_$o|T20C!BE}?Ecb%3Yv^phE2WX9rq zDG2Mg27i2e{3=<&Kksf&wjCQTBXn;Tfq;aNagr=D&=8Hr<#M&ur*nkNxwQl{LRee6huyzd2nWGZ59-M|<6T zlgk>~SDT(it+_0&|BvxJR7AHi%Z1tP!zt(ED-C`yMj85#_pIwgK)k}08-6J2;WGEH zrW4o^&;0-V96O?7{FRQKuEo5h$@5zNDTGU4js76-u?r7k6C!E&jb`1o8V`o^h%a6Q zKLZ7kOZxaY6792IX(_nBZvM)knsZIYlk3RfSvBAXXGhG8x8I;ll|LDB=q|Dc^N%&} zovn}@f!k4tmH!emwxfb_TK%exf8;X4f@#I0J!p}$xb%xpHIBrywh8-CRC)5*XzxV< zET6Q@b~}b$;b*&?^}d2PF_~jCOG54KJ6W1m_scZa9S*+*LD9;nWoZ)_c|zseulF~p zI9pb_3-4vT0p4v#nq-Mz-X!5muF9RWX6>sM*MLfG_X?RIdb@Z&P-a$}-YUh4k9HrC zDr+CT3@qQ_Be&|7LF% z*C^nt4n^X}IpvB`eQ9BaJ|*|HYpK+}{PGaDc$Kx}X-BsiRHFArw1JRR*q_g=EuCW4 z&N9`3csm!~#fwt!$Aaj=P+sgimlu3;3&e zGF^bzJ1j(~T$N$an$%1EnM~u32*$dRwRDRFM727!IY4E97v=Z$1gVR=qxh*GFHD)~ zu6(z;@%UpdC+oVigOj5wKaLSrgek~VVlcnDS?uRRy7tNNnBDBF7Ni%qs5M*9Deu)U z)^_C|I-vBHz7i+evVM4S9z~AS9aa>EQ9Y)%8-1D9iLO|r)K_{Z-l9$oZY_>tQjqw- zEho}^o1BaUsbzQr6A zNxg`>H!`W(5GwsM6sS)`g(Pb+pd?|-Ae8rn>8-o0MsHw&J4(xy>l0O|#g_#>pV`(We32kQVDO1qHXo=&^9Fpp2u z4#b`hCUl`Oe$BG-loow9YhX~80IjZBV^N2o%5(x#u+|-6MHec=b-#nCUqxmYR1bpc zLEKUr2Y(9Jns7s6!A%%wTx80CpOgsi-65RR(ChSc2wuU_bnK6HWWja49arl`+=N05 zC``Ob9LnoEI_~497JTdJla<^`R$s8is$I=Wkzc_UUwVd}eK%7?8jXRB{5{y5Y(YK7 z*M9u~DI=X}%)$12QD(Z%7w(6GgV1z?)=+*AtL%=mI52=R;3jtQms!%n^f_zbUa&e$ zFlS>J?dxrob#WF8QP%=TcV~dy61qxTiel|(CI>S<8rGdyeaw2R37mBCgD;9Zk9(}L zY0lzul$$^T-TW1$6CXJJq;V{nOg#_FY4{YCW^;jhsh|DnK^iyFnam!B{cmf_X<0Vue^o4-9|3GU5|PY?T3RQ`lHqk!%&Zc~+Ml&%v?$VvaOPw=D3SX5N`>FT?h$xmX4QMa_iciQC5&Nw{peIFo z;x0)Y2&wi7E=Y{J!2}OM9v7$TF{RcC_P~g~fF2aWydg=b9M>txQ`Pt5(Dx^Dv0tI}@lms_-v@M7QIFt5hzTAbrLER4V z1La0kO{R2~y1eLNTOtPrf%*gz-p|nEW@r#{=BVT9ZIkeWdWn{Gt3?6`wn6bx1%9hg zxe^0PF?%b@KgDn9eauEnG;&2@QoT{mUQ6^4M8&aale4BGdM=8L;cAm+t0lS}g54>2 zU$Cnp8im0Bk=g{UuZW(H%B{)LZ@l-!Z`@GC-Pu*9;~sQ&KO|`By5EF5wPz1&05nXn zUHeQbA(yInv4UNk-cLuD7J8_p2#6re!Gistn!M7`|~c_ZkLF3kdvRKOpAj0*tJ g{$KdB1>F^$)^v|4Upi#KB56Y7!=uKW3^Qc>KNT~QHUIzs literal 0 HcmV?d00001 diff --git a/Sources/Resources/iOS/AppIcon.appiconset/icon_120.png b/Sources/Resources/iOS/AppIcon.appiconset/icon_120.png new file mode 100644 index 0000000000000000000000000000000000000000..9d5f9a8ea1e436265b4d879577f0c7f8722e654d GIT binary patch literal 1406 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 LNkvXXu0mjf@j)>% literal 0 HcmV?d00001 diff --git a/Sources/Resources/iOS/AppIcon.appiconset/icon_167.png b/Sources/Resources/iOS/AppIcon.appiconset/icon_167.png new file mode 100644 index 0000000000000000000000000000000000000000..8d4d35e9509c41ef231056fb172de110f7d11efe GIT binary patch literal 1849 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 literal 0 HcmV?d00001 diff --git a/Sources/Resources/iOS/AppIcon.appiconset/icon_40.png b/Sources/Resources/iOS/AppIcon.appiconset/icon_40.png new file mode 100644 index 0000000000000000000000000000000000000000..d22550ea5f6d8108621ae0ee901223c7a9c51a12 GIT binary patch literal 503 zcmV>6$P~tI1DNmb_i)X za8fV{Xbu>nI=4g|E5FB^m_kx^*AUi;E zigV#Gw;+LlG52!dQjn=N=`IN;fh46^6ONm1hq;Hrd0+305@gIp_9ltRR|{5cYQmFt=xi-}RZN$Z1IgnRITYCWV^jntI zN(^}WusItHTY8}O#q93hH{j%9eK7NIPzg*Gu#LEv3l`lZT0uiboN?h!?&9U^Jfv1FEwlzXvrnN+ALspg7Wyd5=VnvgyM2YuCm4o(H>8E~Sr zI0w=T&SdoBo&pNQ-8+o&@${v4ai@ZE)j?7&O=lN(s6RJFtt*Le>_Xi`O5F^CKPl=D t4z)yJB~W00@Gn}w><;VPdemm_`T=8-*d%pR!qWf%002ovPDHLkV1nb`>4yLS literal 0 HcmV?d00001 diff --git a/Sources/Resources/iOS/AppIcon.appiconset/icon_58.png b/Sources/Resources/iOS/AppIcon.appiconset/icon_58.png new file mode 100644 index 0000000000000000000000000000000000000000..f44e57eb6066d40a724140c6d4b141cd62a8fb51 GIT binary patch literal 683 zcmV;c0#yBpP)q$by`wBUz$!YTPR#wZ>%h8?0~+&cuJ7AxK%7j{jd(YZn~Ut zryg`xNkWFg#e&ucuu1|_8c-5g?_iBJS_)*RW_H0ILxs9Y1vI(hGfw+@wSQl)e@OH8 zt_Fen1Q(ia$73HthQeySQ5823=>?>}-ZoE{%2ZfIanv@s)V4sWPhVKAH_Cf4$^q$u zp)68ZGNdFdaso&J$yselpe8p{Lb_mmT*a|Ka$%7=QBFus8e`7ZPFjt{RgCFo)2vre zh^q(@rJi8k!AdmcT%m8;a%;1Ll?EPiwK2>Q)zRKnc>CI?a4vT-$D}dbEdo>>xtaqQ zOV~R(z`m<5LL!-5JycA05eieRbgm$wI#*kVtG$}tYhBOg(Lk^77JvTUE+wV{XrEzq z^Re&>e0%>6qjfX~AgM+tFSiie%?>aG(zl)~NFW=p#F`I2p6N&zeJj1+w*%LOX|NlslCtR%2&yy(BwZyoz9 z7ue_ekcUhv^!N=GhO>HqK7O;0-&7E&K5$=PZd!{y@z##>t~pyp4y4|3iQK(V-KCBz zArTcUlMRG`UOHBJW2CA Rg<}8!002ovPDHLkV1jegEtLQO literal 0 HcmV?d00001 diff --git a/Sources/Resources/iOS/AppIcon.appiconset/icon_60.png b/Sources/Resources/iOS/AppIcon.appiconset/icon_60.png new file mode 100644 index 0000000000000000000000000000000000000000..ca052327ebf98ae838799b87be34abea8b1750f2 GIT binary patch literal 696 zcmV;p0!RIcP)*|9E-SF@VN^tK6{qVHb6LwOOTh>4a7} zU}GV3!Rrxd#R*tj-R9FL%G>b`;faC~T}1 zTe}C~USgqjYncQb0-Lz*aypXS?N-@r?D-e(7FYVn!_$wZqOl+4cxpR zV;ZLn+m8#%cNRngmxkqp#*_g_!gfiyBn1K6?3RG_L5EmIN{1z3Q%&Pkc2ZpNS;pLU z>w33^30X!7yXISuxpZ*!$6~l5%w6>axA69Lu$%)r)-r-{q-_TQkDbmbD|6p+7f$Fg z%eM9r3Z{f@lTdn- zz5Rx#!{!;b*B|R3fc^bD%-(P*&?0j<#BNU5Ng2)!Dh_P3D+TI2rN;(w{&EAHF@12s zj$OiRcTorh>`GfD1E*T%v`XEepzQ;$ff>7I;~;6(^-us~8;iBfxl7{MexmEcl5;KB zBOjzR%DrMs-dv#X0Gs8K&^FkR2YQ&&aS7m#b1wh)Rm3CZpN{r74|B6U eS3#!$WBvfSj7U|`7G}@@0000aInb!_8ZBT*Q3;)J$v@_8x8reb8jd0O5*+BA{M%5Xc#b!%196Ja?ew9 zgY%y+pwGLfqvEttbHMXJXtiP9f~af3^F+{U!Q6s)hdPP?aLaM2OI%ag=b6B*W%~Y3 z9WMV!EHpj9n=>5WC}`HWpqH>OfLB^(xns=`F-(k>aEXCF^JLH``IYgn_N}E90eBR1qG|E|mO42Wn%?Zgw$MQB za}B~vftYF`*>zxQhT(En4F?3!A=sxM)oF%^v0ukg%0|-SF)%@d98a-C2pkkp1q{_8A=g;S=5*90$N%Qg|dk?Wp-}PaF18gM)5!i7H{qrHZ}^W0vu>u&*{e$n9SgV9k>mnaj0gml|{( zXb~)&?VImexxhg;AJ{LX4;60sDU$^7mK~PilBR}zsSlY@473eG#M(DZ1}JHAr%uiz zPP94DHe?~@u5}i`n1!|hh%tD%57@H}Y#HK!46nF^TZA|ez$3j5w1OZ~KB)t}t!Wb> zNx#d;wGZuW%`p)ShmDl4yQ05vZ8HE-+ZZ0puP=Y(zi?e@88*nR@wXsC%)1E?+O@+L zlxr!>l(Ciop(PvbnSjyu#0px0Lx>c;V@NJzMuGRuR4-kVbuN-(Bj%U6*14!!^D$c) zBz6_BH6L3$Au5<0QwK}`z%WplHJ}yu5A3b=CrJm(UP1cAMzp3ztKim>bDn!2>CWWX dvuBSA^B;lItv+7Sr9%J!002ovPDHLkV1mukq+S33 literal 0 HcmV?d00001 diff --git a/Sources/Resources/iOS/AppIcon.appiconset/icon_87.png b/Sources/Resources/iOS/AppIcon.appiconset/icon_87.png new file mode 100644 index 0000000000000000000000000000000000000000..07af9707ad7a421d13da4cebda3c5aba08e35aee GIT binary patch literal 1039 zcmV+q1n~QbP) zJ&xNj5QRy>CrG7&j?WMvsd5A(WtuJa6zR6kMYc`t0|ZEb04Y+YcF2O&UO|BXYe5jA z#GjerP}XbKuy-x$^YhbC;*NyawQJX|T~v~#Z=lrML2OvY{L5yP^@m#r3I#gpm+uv7 zE@a6ata-c!UsKN~!5OgR0@f@*OcfRMHNdhaSOW;O7U(6wk{YZb07?xy1XxmmH5H*! zK%N8Kfp3L5SjzE8OxGG_P$v!F-@QIQUSH7MdjNZ9Ah4?7E1R=TeR=~57}dEsJE$-+ zFfb0+wZ2Lr`_7d$!774!)F0ClTxh^xa8tml3Nx#5d~0AK0E5Gg1*>SMTaR_87V9-f~3(?#Fa|7!_^}#}y zWF4eyUB@b>P<>56Lk=!+Z`J{A?Euya*c6Ddt_D4z?FuUy?iO7e zVxe`g7!^a;`sqVzrMMTwxm$59w0l`q3tC?A9CPWE8mA<(CWqriNS+4J@4- zEAB344OcF>w}q%+4L24rSI8arN+DI0kk_`u-nl96b;ZHOO~B1n?WjOoh=<|cA3Ip3u`r68Q&AT`FS!&7gx1#!^~seS*Dgf@+r`gECSaii z0vEe1qZZUT;O?F>korU7J)5X*uGI?8VR}`QrfF`%qroM$i4+xslq1g@LIoy1sC%B|v?N$bp z_Pd*;AN1oJ2mx0REerhiF|O{_#Rl`nNB0QY?BCd3yLJgM{Rd~d6AQLSjy?bY002ov JPDHLkV1iAC;v4_~ literal 0 HcmV?d00001 diff --git a/Sources/Resources/macOS/MiniPlayer.appiconset/Contents.json b/Sources/Resources/macOS/MiniPlayer.appiconset/Contents.json new file mode 100644 index 0000000..d040faf --- /dev/null +++ b/Sources/Resources/macOS/MiniPlayer.appiconset/Contents.json @@ -0,0 +1,68 @@ +{ + "images": [ + { + "filename": "icon_16.png", + "idiom": "mac", + "scale": "1x", + "size": "16x16" + }, + { + "filename": "icon_16@2x.png", + "idiom": "mac", + "scale": "2x", + "size": "16x16" + }, + { + "filename": "icon_32.png", + "idiom": "mac", + "scale": "1x", + "size": "32x32" + }, + { + "filename": "icon_32@2x.png", + "idiom": "mac", + "scale": "2x", + "size": "32x32" + }, + { + "filename": "icon_128.png", + "idiom": "mac", + "scale": "1x", + "size": "128x128" + }, + { + "filename": "icon_128@2x.png", + "idiom": "mac", + "scale": "2x", + "size": "128x128" + }, + { + "filename": "icon_256.png", + "idiom": "mac", + "scale": "1x", + "size": "256x256" + }, + { + "filename": "icon_256@2x.png", + "idiom": "mac", + "scale": "2x", + "size": "256x256" + }, + { + "filename": "icon_512.png", + "idiom": "mac", + "scale": "1x", + "size": "512x512" + }, + { + "filename": "icon_512@2x.png", + "idiom": "mac", + "scale": "2x", + "size": "512x512" + } + ], + "info": { + "author": "MiniPlayer", + "version": 1 + } +} \ No newline at end of file diff --git a/Sources/Resources/macOS/MiniPlayer.appiconset/icon_128.png b/Sources/Resources/macOS/MiniPlayer.appiconset/icon_128.png new file mode 100644 index 0000000000000000000000000000000000000000..bd90b0183571f5749f8b15da6f8a409fc3617ac5 GIT binary patch literal 1542 zcmV+h2Ko7kP) zJ&x2s5QXg#Cm@<&hCKrkL>vJTZn6QVAS31?n-cE2mz;BvWKE|<&Ya=H4_Nbw_w!;3S;?^x97^b6G^lrML~^#B3- zWp2Da5J0}fjn@mpu5|<4d|tJV|7hL()BA^}&mV5D2Fpn>S~9-XYzt77f-q_~pUQMi zFqA;>Y)~j})3>%oA`GAjz*+s0OwSQF47n*VN;hAd@sdEufnbzszINlKfN%+d=JNm; zvSz;IeHtZIztlm3(D}>DzkfeI{2rvFfQX|2OygUl_k^%*;p#aH2*n9NQT@;Zj6K($ zDz-PR{-vlO*h&G`1b{N1vcWnezXh@VQyOq40b2rCJ4b)o*q^7WKNU6vViI5;sL8+@ z2&5Um+^(8^n#||w3r5Q7Uk*+Q1X7LP(zIVW)t{Q5{u@;akO9yV`P$5%wKTRw7!a%h zKr#i?ny=OPrHM5lP&J1;N#>`9Yd1etYGjG2EeVn<5hsFDSS%S2l?G}Ppwv*S=BFx2 zfVBou4FGfW=R(kf`6Upf=3_#DauiV7^z~$Zs#0THo5HoD0PqBG^YIMDNCMXN0KHaz zD()+SJL>A6O?UJEhad+A=oBDN0LzDZEu!f7Q30^Lnn#)-LD_Mh?Q{Jrjz@wi}5Gg>G0ABqvQ=ka|tBW}_LC~54B5w?F(Fq*@>go^S;chUZqvQo4Qk%c= zmP83GF+hyp-r{68h@AcV?&+gXkO zGzC&=gy4uc4Vat)dQSsX05rw_Rti`JAyn+k&SLzRDkuN}YZ@>=1zbvjRMH{9ka++s zrU9h70H7oVdIMpHwdm6V1d}8|fU#(_iv(y@Fq{Tm0Z^L)mOG5?&jkEiMN9a zoj(nCufN@(7!mC53`lCYgCwT&NYJ9f}gzDodF zsy`YtzN!h#8HD}kH-ki3Fh69RWGY=d*i`~(H6Bx408m=}u><3~0w7nhBjZs|1WD=x za;rZIHy`UFQ!xP22ddQkczv&GpP+9Z>2?aRV!GIC0o>ETR`qMF_<*>^pb7wO1E|$_ zihBo5UJYDUzh&cFg$e-oG+?3XgVc8hNgdd!`lqE>Qnydqt>frZ0CfszScfNRfvL$J zz(oW=Zp?D`0+y@)*!biSvIKAlWZqlQ3_wrKmc{1=k@f(d0`l%G0s){T1snnx^P!#^ z29^Lm73h3q9Qk431d6A?di8U>MHKwy(Iw`3YS2bM$;+clC|03ze|BY3Jg(@={0?u*dCz904f-wK+|hg)!|D^ zfu628Kp(X=9pY&M!MaYBhwDx20XWVPxL|!~UJ&9C@TztEK`Yp&1Uf+#9!i8e2zY`{ sT#`B5fvA^Hu`ZX(<#M@Pt^rzq0PMN-w;M1&07*qoM6N<$g8AgFfB*mh literal 0 HcmV?d00001 diff --git a/Sources/Resources/macOS/MiniPlayer.appiconset/icon_128@2x.png b/Sources/Resources/macOS/MiniPlayer.appiconset/icon_128@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..42b83dc70cc3769ec6146542b639426431afc773 GIT binary patch literal 3498 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 PUkI12t`609Y~KF>E>1W0 literal 0 HcmV?d00001 diff --git a/Sources/Resources/macOS/MiniPlayer.appiconset/icon_16.png b/Sources/Resources/macOS/MiniPlayer.appiconset/icon_16.png new file mode 100644 index 0000000000000000000000000000000000000000..4d52787e055f6fcc04a124270da65a3ba877962e GIT binary patch literal 271 zcmV+q0r38bP)nTVRTC8G_RbAi!A7;LUL4{8o@5 z*bKr5M4aHrd9YU=gKU?T_r_{~iEk8`^I{P~;(sf{R?`zvU=1%qkK#0+37I3Y+8RX? zq!C>+x_2012?<#J5Qgp1o`5RFE_((fs5nAINs}U{prhs@X{mDnB#@9OD5;lqu~n|H$cRLa8PAMo zcuW&z<(dDR$9iq&{@Hx~plwg*-xdww-J<|)g?LyGNB`SRuY&MW@m!EI2~dRaoOrEp zYV*UH>xLbN6a7s(7fCZLXH5jl7+{Wz`^%~z zdw)tiZBIH6O|?>%eQm}+HUpDUn0*TtL>r_7CV4x6%1Sc}oOr%10~f#oA=wu|(pwD# zCXRiS0CToNU~5ZXL{FWHDN)J1yxhEz;w%6M!C3_0PDP#r(1J+!39r2q=0KW_>2NdB nLRf5nH#|O+Cb!nV5RV!kKJu}AZ4dm~00000NkvXXu0mjfEIqv< literal 0 HcmV?d00001 diff --git a/Sources/Resources/macOS/MiniPlayer.appiconset/icon_256.png b/Sources/Resources/macOS/MiniPlayer.appiconset/icon_256.png new file mode 100644 index 0000000000000000000000000000000000000000..42b83dc70cc3769ec6146542b639426431afc773 GIT binary patch literal 3498 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 PUkI12t`609Y~KF>E>1W0 literal 0 HcmV?d00001 diff --git a/Sources/Resources/macOS/MiniPlayer.appiconset/icon_256@2x.png b/Sources/Resources/macOS/MiniPlayer.appiconset/icon_256@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..e78311bae51936241bcff3cfb5d2e82ff90bd188 GIT binary patch literal 6485 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 literal 0 HcmV?d00001 diff --git a/Sources/Resources/macOS/MiniPlayer.appiconset/icon_32@2x.png b/Sources/Resources/macOS/MiniPlayer.appiconset/icon_32@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..2ff0f7ed318b9fcf4cd7df39f5848da12569c148 GIT binary patch literal 780 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 literal 0 HcmV?d00001 diff --git a/Sources/Resources/zh-Hans.lproj/Localizable.strings b/Sources/Resources/zh-Hans.lproj/Localizable.strings new file mode 100644 index 0000000..626acff --- /dev/null +++ b/Sources/Resources/zh-Hans.lproj/Localizable.strings @@ -0,0 +1,31 @@ +"play_pause" = "播放/暂停"; +"prev" = "上一首"; +"next" = "下一首"; +"fullscreen" = "全屏"; +"vol_up" = "音量+"; +"vol_down" = "音量-"; +"repeat_mode" = "循环模式"; +"open_file" = "打开文件..."; +"add_url" = "添加URL..."; +"menu_playback" = "播放"; +"menu_file" = "文件"; +"playlist" = "播放列表"; +"add_file" = "📂 添加文件"; +"add_url_btn" = "🔗 添加URL"; +"items_count" = "项"; +"no_media" = "暂无媒体"; +"add_media_url" = "添加媒体URL"; +"cancel" = "取消"; +"add" = "添加"; +"select_track" = "选择音轨"; +"track" = "音轨"; +"audio_track" = "🎵 音轨"; +"close" = "关闭"; +"repeat_none" = "不循环"; +"repeat_single" = "单曲循环"; +"repeat_all" = "列表循环"; +"now_playing" = "正在播放: %@"; +"repeat_mode_label" = "循环模式: %@"; +"invalid_url" = "无效URL"; +"open" = "打开"; +"list" = "列表"; diff --git a/generate_icons.py b/generate_icons.py new file mode 100644 index 0000000..b2e560c --- /dev/null +++ b/generate_icons.py @@ -0,0 +1,217 @@ +#!/usr/bin/env python3 +"""Generate MiniPlayer app icons (tri-color play button + ring)""" + +from PIL import Image, ImageDraw +import math +import os + +def create_icon(size): + """Create icon at given size""" + img = Image.new('RGBA', (size, size), (0, 0, 0, 0)) + draw = ImageDraw.Draw(img) + + # Background: dark rounded rect + margin = int(size * 0.05) + radius = int(size * 0.18) + draw.rounded_rectangle( + [margin, margin, size - margin, size - margin], + radius=radius, + fill=(28, 28, 30, 255) + ) + + cx, cy = size / 2, size / 2 + ring_radius = size * 0.38 + ring_width = size * 0.06 + tri_size = size * 0.28 + + # Colors + RED = (255, 59, 48) + GREEN = (52, 199, 89) + BLUE = (0, 122, 255) + + # === Outer Ring: 3 arc segments === + # Red: 150-270°, Green: 270-30°, Blue: 30-150° + # Draw as thick arcs + inner_r = ring_radius - ring_width / 2 + outer_r = ring_radius + ring_width / 2 + + def draw_arc_segment(color, start_deg, end_deg): + """Draw a thick arc segment""" + for angle in range(int(start_deg * 10), int(end_deg * 10)): + a = angle / 10.0 + rad = math.radians(a) + ix = cx + inner_r * math.cos(rad) + iy = cy + inner_r * math.sin(rad) + ox = cx + outer_r * math.cos(rad) + oy = cy + outer_r * math.sin(rad) + draw.line([(ix, iy), (ox, oy)], fill=color, width=max(1, int(size * 0.005))) + + # Ring segments (start from top, clockwise) + # Red: top-left to bottom-left (180° arc, offset) + draw_arc_segment(RED, -60, 60) # right side + draw_arc_segment(GREEN, 60, 180) # bottom + draw_arc_segment(BLUE, 180, 300) # left/top + + # === Play Triangle: split into 3 colored sections from center === + # Triangle pointing right: vertices relative to center + # Shift slightly right for visual centering of play button + offset_x = tri_size * 0.08 + + # Triangle vertices (pointing right) + top = (cx - tri_size * 0.4 + offset_x, cy - tri_size * 0.55) + bottom = (cx - tri_size * 0.4 + offset_x, cy + tri_size * 0.55) + right = (cx + tri_size * 0.55 + offset_x, cy) + + # Center of triangle + tcx = (top[0] + bottom[0] + right[0]) / 3 + tcy = (top[1] + bottom[1] + right[1]) / 3 + + # Draw 3 sections from center to each edge + # Section 1 (Red): center -> top -> right + draw.polygon([ + (tcx, tcy), + top, + right + ], fill=RED) + + # Section 2 (Green): center -> right -> bottom + draw.polygon([ + (tcx, tcy), + right, + bottom + ], fill=GREEN) + + # Section 3 (Blue): center -> bottom -> top + draw.polygon([ + (tcx, tcy), + bottom, + top + ], fill=BLUE) + + # Thin white lines from center to vertices (separators) + line_w = max(1, int(size * 0.004)) + draw.line([(tcx, tcy), top], fill=(255, 255, 255, 180), width=line_w) + draw.line([(tcx, tcy), bottom], fill=(255, 255, 255, 180), width=line_w) + draw.line([(tcx, tcy), right], fill=(255, 255, 255, 180), width=line_w) + + return img + + +def generate_macos_icons(output_dir): + """Generate macOS .appiconset""" + appiconset = os.path.join(output_dir, "MiniPlayer.appiconset") + os.makedirs(appiconset, exist_ok=True) + + sizes = { + "icon_16": 16, + "icon_16@2x": 32, + "icon_32": 32, + "icon_32@2x": 64, + "icon_128": 128, + "icon_128@2x": 256, + "icon_256": 256, + "icon_256@2x": 512, + "icon_512": 512, + "icon_512@2x": 1024, + } + + images_json = [] + for name, px in sizes.items(): + fname = f"{name}.png" + icon = create_icon(px) + icon.save(os.path.join(appiconset, fname)) + + # Parse size and scale + if "@2x" in name: + base = name.replace("@2x", "") + scale = "2x" + sz = base.replace("icon_", "") + else: + scale = "1x" + sz = name.replace("icon_", "") + + images_json.append({ + "filename": fname, + "idiom": "mac", + "scale": scale, + "size": f"{sz}x{sz}" + }) + print(f" {fname}: {px}x{px}") + + # Write Contents.json + import json + contents = { + "images": images_json, + "info": {"author": "MiniPlayer", "version": 1} + } + with open(os.path.join(appiconset, "Contents.json"), "w") as f: + json.dump(contents, f, indent=2) + + print(f" Contents.json written") + + +def generate_ios_icons(output_dir): + """Generate iOS AppIcon set""" + appiconset = os.path.join(output_dir, "AppIcon.appiconset") + os.makedirs(appiconset, exist_ok=True) + + # iOS icon sizes (points x scale = pixels) + ios_sizes = [ + ("20x20", "2x", 40), + ("20x20", "3x", 60), + ("29x29", "2x", 58), + ("29x29", "3x", 87), + ("40x40", "2x", 80), + ("40x40", "3x", 120), + ("60x60", "2x", 120), + ("60x60", "3x", 180), + ("76x76", "2x", 152), + ("83.5x83.5", "2x", 167), + ("1024x1024", "1x", 1024), + ] + + images_json = [] + for sz, scale, px in ios_sizes: + fname = f"icon_{px}.png" + fpath = os.path.join(appiconset, fname) + if not os.path.exists(fpath): + icon = create_icon(px) + icon.save(fpath) + images_json.append({ + "filename": fname, + "idiom": "ios-marketing" if px == 1024 else "iphone" if "x20" in sz or "x29" in sz or "x40" in sz or "x60" in sz else "ipad", + "scale": scale, + "size": sz + }) + print(f" {fname}: {px}x{px}") + + import json + contents = { + "images": images_json, + "info": {"author": "MiniPlayer", "version": 1} + } + with open(os.path.join(appiconset, "Contents.json"), "w") as f: + json.dump(contents, f, indent=2) + + print(f" Contents.json written") + + +if __name__ == "__main__": + base = os.path.dirname(os.path.abspath(__file__)) + + print("=== macOS Icons ===") + macos_dir = os.path.join(base, "Sources", "Resources", "macOS") + generate_macos_icons(macos_dir) + + print("\n=== iOS Icons ===") + ios_dir = os.path.join(base, "Sources", "Resources", "iOS") + generate_ios_icons(ios_dir) + + # Also save a preview + preview = create_icon(512) + preview_path = os.path.join(base, "build", "icon_preview.png") + os.makedirs(os.path.dirname(preview_path), exist_ok=True) + preview.save(preview_path) + print(f"\nPreview: {preview_path}") + + print("\nDone!")