mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
[WIP] Copy widget folder
This commit is contained in:
parent
6ac330fb33
commit
a2a8bdbd30
31
Telegram/LegacyWidget/Info.plist
Normal file
31
Telegram/LegacyWidget/Info.plist
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||||
|
<key>CFBundleDisplayName</key>
|
||||||
|
<string>${APP_NAME}</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>$(EXECUTABLE_NAME)</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>$(PRODUCT_NAME)</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>XPC!</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>$(PRODUCT_BUNDLE_SHORT_VERSION)</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>${BUILD_NUMBER}</string>
|
||||||
|
<key>NSExtension</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSExtensionPointIdentifier</key>
|
||||||
|
<string>com.apple.widget-extension</string>
|
||||||
|
<key>NSExtensionPrincipalClass</key>
|
||||||
|
<string>TodayViewController</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
172
Telegram/LegacyWidget/PeerNode.swift
Normal file
172
Telegram/LegacyWidget/PeerNode.swift
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
import Foundation
|
||||||
|
import UIKit
|
||||||
|
import WidgetItems
|
||||||
|
|
||||||
|
private extension UIColor {
|
||||||
|
convenience init(rgb: UInt32) {
|
||||||
|
self.init(red: CGFloat((rgb >> 16) & 0xff) / 255.0, green: CGFloat((rgb >> 8) & 0xff) / 255.0, blue: CGFloat(rgb & 0xff) / 255.0, alpha: 1.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private let UIScreenScale = UIScreen.main.scale
|
||||||
|
private func floorToScreenPixels(_ value: CGFloat) -> CGFloat {
|
||||||
|
return floor(value * UIScreenScale) / UIScreenScale
|
||||||
|
}
|
||||||
|
|
||||||
|
private let gradientColors: [NSArray] = [
|
||||||
|
[UIColor(rgb: 0xff516a).cgColor, UIColor(rgb: 0xff885e).cgColor],
|
||||||
|
[UIColor(rgb: 0xffa85c).cgColor, UIColor(rgb: 0xffcd6a).cgColor],
|
||||||
|
[UIColor(rgb: 0x665fff).cgColor, UIColor(rgb: 0x82b1ff).cgColor],
|
||||||
|
[UIColor(rgb: 0x54cb68).cgColor, UIColor(rgb: 0xa0de7e).cgColor],
|
||||||
|
[UIColor(rgb: 0x4acccd).cgColor, UIColor(rgb: 0x00fcfd).cgColor],
|
||||||
|
[UIColor(rgb: 0x2a9ef1).cgColor, UIColor(rgb: 0x72d5fd).cgColor],
|
||||||
|
[UIColor(rgb: 0xd669ed).cgColor, UIColor(rgb: 0xe0a2f3).cgColor],
|
||||||
|
]
|
||||||
|
|
||||||
|
private func avatarRoundImage(size: CGSize, source: UIImage) -> UIImage? {
|
||||||
|
UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
|
||||||
|
let context = UIGraphicsGetCurrentContext()
|
||||||
|
|
||||||
|
context?.beginPath()
|
||||||
|
context?.addEllipse(in: CGRect(x: 0.0, y: 0.0, width: size.width, height: size.height))
|
||||||
|
context?.clip()
|
||||||
|
|
||||||
|
source.draw(in: CGRect(origin: CGPoint(), size: size))
|
||||||
|
|
||||||
|
let image = UIGraphicsGetImageFromCurrentImageContext()
|
||||||
|
UIGraphicsEndImageContext()
|
||||||
|
return image
|
||||||
|
}
|
||||||
|
|
||||||
|
private let deviceColorSpace: CGColorSpace = {
|
||||||
|
if #available(iOSApplicationExtension 9.3, *) {
|
||||||
|
if let colorSpace = CGColorSpace(name: CGColorSpace.displayP3) {
|
||||||
|
return colorSpace
|
||||||
|
} else {
|
||||||
|
return CGColorSpaceCreateDeviceRGB()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return CGColorSpaceCreateDeviceRGB()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
private func avatarViewLettersImage(size: CGSize, peerId: Int64, accountPeerId: Int64, letters: [String]) -> UIImage? {
|
||||||
|
UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
|
||||||
|
let context = UIGraphicsGetCurrentContext()
|
||||||
|
|
||||||
|
context?.beginPath()
|
||||||
|
context?.addEllipse(in: CGRect(x: 0.0, y: 0.0, width: size.width, height: size.height))
|
||||||
|
context?.clip()
|
||||||
|
|
||||||
|
let colorIndex = abs(Int(accountPeerId + peerId))
|
||||||
|
|
||||||
|
let colorsArray = gradientColors[colorIndex % gradientColors.count]
|
||||||
|
var locations: [CGFloat] = [1.0, 0.0]
|
||||||
|
let gradient = CGGradient(colorsSpace: deviceColorSpace, colors: colorsArray, locations: &locations)!
|
||||||
|
|
||||||
|
context?.drawLinearGradient(gradient, start: CGPoint(), end: CGPoint(x: 0.0, y: size.height), options: CGGradientDrawingOptions())
|
||||||
|
|
||||||
|
context?.setBlendMode(.normal)
|
||||||
|
|
||||||
|
let string = letters.count == 0 ? "" : (letters[0] + (letters.count == 1 ? "" : letters[1]))
|
||||||
|
let attributedString = NSAttributedString(string: string, attributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 20.0), NSAttributedString.Key.foregroundColor: UIColor.white])
|
||||||
|
|
||||||
|
let line = CTLineCreateWithAttributedString(attributedString)
|
||||||
|
let lineBounds = CTLineGetBoundsWithOptions(line, .useGlyphPathBounds)
|
||||||
|
|
||||||
|
let lineOffset = CGPoint(x: string == "B" ? 1.0 : 0.0, y: 0.0)
|
||||||
|
let lineOrigin = CGPoint(x: floorToScreenPixels(-lineBounds.origin.x + (size.width - lineBounds.size.width) / 2.0) + lineOffset.x, y: floorToScreenPixels(-lineBounds.origin.y + (size.height - lineBounds.size.height) / 2.0))
|
||||||
|
|
||||||
|
context?.translateBy(x: size.width / 2.0, y: size.height / 2.0)
|
||||||
|
context?.scaleBy(x: 1.0, y: -1.0)
|
||||||
|
context?.translateBy(x: -size.width / 2.0, y: -size.height / 2.0)
|
||||||
|
|
||||||
|
context?.translateBy(x: lineOrigin.x, y: lineOrigin.y)
|
||||||
|
if let context = context {
|
||||||
|
CTLineDraw(line, context)
|
||||||
|
}
|
||||||
|
context?.translateBy(x: -lineOrigin.x, y: -lineOrigin.y)
|
||||||
|
|
||||||
|
let image = UIGraphicsGetImageFromCurrentImageContext()
|
||||||
|
UIGraphicsEndImageContext()
|
||||||
|
return image
|
||||||
|
}
|
||||||
|
|
||||||
|
private let avatarSize = CGSize(width: 50.0, height: 50.0)
|
||||||
|
|
||||||
|
private final class AvatarView: UIImageView {
|
||||||
|
init(accountPeerId: Int64, peer: WidgetDataPeer, size: CGSize) {
|
||||||
|
super.init(frame: CGRect())
|
||||||
|
|
||||||
|
if let path = peer.avatarPath, let image = UIImage(contentsOfFile: path), let roundImage = avatarRoundImage(size: size, source: image) {
|
||||||
|
self.image = roundImage
|
||||||
|
} else {
|
||||||
|
self.image = avatarViewLettersImage(size: size, peerId: peer.id, accountPeerId: accountPeerId, letters: peer.letters)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder aDecoder: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final class PeerView: UIView {
|
||||||
|
let peer: WidgetDataPeer
|
||||||
|
private let avatarView: AvatarView
|
||||||
|
private let titleLabel: UILabel
|
||||||
|
|
||||||
|
private let tapped: () -> Void
|
||||||
|
|
||||||
|
init(primaryColor: UIColor, accountPeerId: Int64, peer: WidgetDataPeer, tapped: @escaping () -> Void) {
|
||||||
|
self.peer = peer
|
||||||
|
self.tapped = tapped
|
||||||
|
self.avatarView = AvatarView(accountPeerId: accountPeerId, peer: peer, size: avatarSize)
|
||||||
|
|
||||||
|
self.titleLabel = UILabel()
|
||||||
|
var title = peer.name
|
||||||
|
if let lastName = peer.lastName, !lastName.isEmpty {
|
||||||
|
title.append("\n")
|
||||||
|
title.append(lastName)
|
||||||
|
}
|
||||||
|
|
||||||
|
let systemFontSize = UIFont.preferredFont(forTextStyle: .body).pointSize
|
||||||
|
let fontSize = floor(systemFontSize * 11.0 / 17.0)
|
||||||
|
|
||||||
|
self.titleLabel.text = title
|
||||||
|
if #available(iOSApplicationExtension 13.0, *) {
|
||||||
|
self.titleLabel.textColor = UIColor.label
|
||||||
|
} else {
|
||||||
|
self.titleLabel.textColor = primaryColor
|
||||||
|
}
|
||||||
|
self.titleLabel.font = UIFont.systemFont(ofSize: fontSize)
|
||||||
|
self.titleLabel.lineBreakMode = .byTruncatingTail
|
||||||
|
self.titleLabel.numberOfLines = 2
|
||||||
|
self.titleLabel.textAlignment = .center
|
||||||
|
|
||||||
|
super.init(frame: CGRect())
|
||||||
|
|
||||||
|
self.addSubview(self.avatarView)
|
||||||
|
self.addSubview(self.titleLabel)
|
||||||
|
|
||||||
|
self.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:))))
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder aDecoder: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateLayout(size: CGSize) {
|
||||||
|
self.avatarView.frame = CGRect(origin: CGPoint(x: floor((size.width - avatarSize.width) / 2.0), y: 0.0), size: avatarSize)
|
||||||
|
|
||||||
|
var titleSize = self.titleLabel.sizeThatFits(size)
|
||||||
|
titleSize.width = min(size.width - 6.0, ceil(titleSize.width))
|
||||||
|
titleSize.height = ceil(titleSize.height)
|
||||||
|
self.titleLabel.frame = CGRect(origin: CGPoint(x: floor((size.width - titleSize.width) / 2.0), y: avatarSize.height + 5.0), size: titleSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc func tapGesture(_ recognizer: UITapGestureRecognizer) {
|
||||||
|
if case .ended = recognizer.state {
|
||||||
|
self.tapped()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
171
Telegram/LegacyWidget/TodayViewController.swift
Normal file
171
Telegram/LegacyWidget/TodayViewController.swift
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
import UIKit
|
||||||
|
import NotificationCenter
|
||||||
|
import BuildConfig
|
||||||
|
import WidgetItems
|
||||||
|
import AppLockState
|
||||||
|
|
||||||
|
private func rootPathForBasePath(_ appGroupPath: String) -> String {
|
||||||
|
return appGroupPath + "/telegram-data"
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc(TodayViewController)
|
||||||
|
class TodayViewController: UIViewController, NCWidgetProviding {
|
||||||
|
private var initializedInterface = false
|
||||||
|
|
||||||
|
private var buildConfig: BuildConfig?
|
||||||
|
|
||||||
|
private var primaryColor: UIColor = .black
|
||||||
|
private var placeholderLabel: UILabel?
|
||||||
|
|
||||||
|
override func viewDidLoad() {
|
||||||
|
super.viewDidLoad()
|
||||||
|
|
||||||
|
let appBundleIdentifier = Bundle.main.bundleIdentifier!
|
||||||
|
guard let lastDotRange = appBundleIdentifier.range(of: ".", options: [.backwards]) else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let baseAppBundleId = String(appBundleIdentifier[..<lastDotRange.lowerBound])
|
||||||
|
|
||||||
|
let buildConfig = BuildConfig(baseAppBundleId: baseAppBundleId)
|
||||||
|
self.buildConfig = buildConfig
|
||||||
|
|
||||||
|
let appGroupName = "group.\(baseAppBundleId)"
|
||||||
|
let maybeAppGroupUrl = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: appGroupName)
|
||||||
|
|
||||||
|
guard let appGroupUrl = maybeAppGroupUrl else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let rootPath = rootPathForBasePath(appGroupUrl.path)
|
||||||
|
|
||||||
|
let presentationData: WidgetPresentationData
|
||||||
|
if let data = try? Data(contentsOf: URL(fileURLWithPath: widgetPresentationDataPath(rootPath: rootPath))), let value = try? JSONDecoder().decode(WidgetPresentationData.self, from: data) {
|
||||||
|
presentationData = value
|
||||||
|
} else {
|
||||||
|
presentationData = WidgetPresentationData(applicationLockedString: "Unlock the app to use the widget", applicationStartRequiredString: "Open the app to use the widget")
|
||||||
|
}
|
||||||
|
|
||||||
|
if let data = try? Data(contentsOf: URL(fileURLWithPath: appLockStatePath(rootPath: rootPath))), let state = try? JSONDecoder().decode(LockState.self, from: data), isAppLocked(state: state) {
|
||||||
|
self.setPlaceholderText(presentationData.applicationLockedString)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.initializedInterface {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self.initializedInterface = true
|
||||||
|
|
||||||
|
let dataPath = rootPath + "/widget-data"
|
||||||
|
|
||||||
|
if let data = try? Data(contentsOf: URL(fileURLWithPath: dataPath)), let widgetData = try? JSONDecoder().decode(WidgetData.self, from: data) {
|
||||||
|
self.setWidgetData(widgetData: widgetData, presentationData: presentationData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func setPlaceholderText(_ text: String) {
|
||||||
|
let fontSize = UIFont.preferredFont(forTextStyle: .body).pointSize
|
||||||
|
let placeholderLabel = UILabel()
|
||||||
|
if #available(iOSApplicationExtension 13.0, *) {
|
||||||
|
placeholderLabel.textColor = UIColor.label
|
||||||
|
} else {
|
||||||
|
placeholderLabel.textColor = self.primaryColor
|
||||||
|
}
|
||||||
|
placeholderLabel.font = UIFont.systemFont(ofSize: fontSize)
|
||||||
|
placeholderLabel.text = text
|
||||||
|
placeholderLabel.sizeToFit()
|
||||||
|
self.placeholderLabel = placeholderLabel
|
||||||
|
self.view.addSubview(placeholderLabel)
|
||||||
|
}
|
||||||
|
|
||||||
|
func widgetPerformUpdate(completionHandler: (@escaping (NCUpdateResult) -> Void)) {
|
||||||
|
completionHandler(.newData)
|
||||||
|
}
|
||||||
|
|
||||||
|
@available(iOSApplicationExtension 10.0, *)
|
||||||
|
func widgetActiveDisplayModeDidChange(_ activeDisplayMode: NCWidgetDisplayMode, withMaximumSize maxSize: CGSize) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private var widgetData: WidgetData?
|
||||||
|
|
||||||
|
private func setWidgetData(widgetData: WidgetData, presentationData: WidgetPresentationData) {
|
||||||
|
self.widgetData = widgetData
|
||||||
|
self.peerViews.forEach {
|
||||||
|
$0.removeFromSuperview()
|
||||||
|
}
|
||||||
|
self.peerViews = []
|
||||||
|
switch widgetData {
|
||||||
|
case .notAuthorized, .disabled:
|
||||||
|
break
|
||||||
|
case let .peers(peers):
|
||||||
|
for peer in peers.peers {
|
||||||
|
let peerView = PeerView(primaryColor: self.primaryColor, accountPeerId: peers.accountPeerId, peer: peer, tapped: { [weak self] in
|
||||||
|
if let strongSelf = self, let buildConfig = strongSelf.buildConfig {
|
||||||
|
if let url = URL(string: "\(buildConfig.appSpecificUrlScheme)://localpeer?id=\(peer.id)") {
|
||||||
|
strongSelf.extensionContext?.open(url, completionHandler: nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
self.view.addSubview(peerView)
|
||||||
|
self.peerViews.append(peerView)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.peerViews.isEmpty {
|
||||||
|
self.setPlaceholderText(presentationData.applicationStartRequiredString)
|
||||||
|
} else {
|
||||||
|
self.placeholderLabel?.removeFromSuperview()
|
||||||
|
self.placeholderLabel = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if let size = self.validLayout {
|
||||||
|
self.updateLayout(size: size)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var validLayout: CGSize?
|
||||||
|
|
||||||
|
private var peerViews: [PeerView] = []
|
||||||
|
|
||||||
|
override func viewDidLayoutSubviews() {
|
||||||
|
super.viewDidLayoutSubviews()
|
||||||
|
|
||||||
|
self.updateLayout(size: self.view.bounds.size)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func updateLayout(size: CGSize) {
|
||||||
|
self.validLayout = size
|
||||||
|
|
||||||
|
if let placeholderLabel = self.placeholderLabel {
|
||||||
|
placeholderLabel.frame = CGRect(origin: CGPoint(x: floor((size.width - placeholderLabel.bounds.width) / 2.0), y: floor((size.height - placeholderLabel.bounds.height) / 2.0)), size: placeholderLabel.bounds.size)
|
||||||
|
}
|
||||||
|
|
||||||
|
let peerSize = CGSize(width: 70.0, height: 100.0)
|
||||||
|
|
||||||
|
var peerFrames: [CGRect] = []
|
||||||
|
|
||||||
|
var offset: CGFloat = 0.0
|
||||||
|
for _ in self.peerViews {
|
||||||
|
let peerFrame = CGRect(origin: CGPoint(x: offset, y: 10.0), size: peerSize)
|
||||||
|
offset += peerFrame.size.width
|
||||||
|
if peerFrame.maxX > size.width {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
peerFrames.append(peerFrame)
|
||||||
|
}
|
||||||
|
|
||||||
|
var totalSize: CGFloat = 0.0
|
||||||
|
for i in 0 ..< peerFrames.count {
|
||||||
|
totalSize += peerFrames[i].width
|
||||||
|
}
|
||||||
|
|
||||||
|
let spacing: CGFloat = floor((size.width - totalSize) / CGFloat(peerFrames.count))
|
||||||
|
offset = floor(spacing / 2.0)
|
||||||
|
for i in 0 ..< peerFrames.count {
|
||||||
|
let peerView = self.peerViews[i]
|
||||||
|
peerView.frame = CGRect(origin: CGPoint(x: offset, y: 16.0), size: peerFrames[i].size)
|
||||||
|
peerView.updateLayout(size: peerFrames[i].size)
|
||||||
|
offset += peerFrames[i].width + spacing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
10
Telegram/LegacyWidget/Widget-AppStore.entitlements
Normal file
10
Telegram/LegacyWidget/Widget-AppStore.entitlements
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>com.apple.security.application-groups</key>
|
||||||
|
<array>
|
||||||
|
<string>group.org.telegram.TelegramHD</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
10
Telegram/LegacyWidget/Widget-AppStoreLLC.entitlements
Normal file
10
Telegram/LegacyWidget/Widget-AppStoreLLC.entitlements
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>com.apple.security.application-groups</key>
|
||||||
|
<array>
|
||||||
|
<string>group.ph.telegra.Telegraph</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
4
Telegram/LegacyWidget/Widget-Bridging-Header.h
Normal file
4
Telegram/LegacyWidget/Widget-Bridging-Header.h
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
#ifndef Widget_Bridging_Header_h
|
||||||
|
#define Widget_Bridging_Header_h
|
||||||
|
|
||||||
|
#endif
|
10
Telegram/LegacyWidget/Widget-Fork.entitlements
Normal file
10
Telegram/LegacyWidget/Widget-Fork.entitlements
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>com.apple.security.application-groups</key>
|
||||||
|
<array>
|
||||||
|
<string>group.fork.telegram.Telegram-iOS</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
10
Telegram/LegacyWidget/Widget-HockeyApp.entitlements
Normal file
10
Telegram/LegacyWidget/Widget-HockeyApp.entitlements
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>com.apple.security.application-groups</key>
|
||||||
|
<array>
|
||||||
|
<string>group.org.telegram.Telegram-iOS</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
1
Telegram/LegacyWidget/ar.lproj/InfoPlist.strings
Normal file
1
Telegram/LegacyWidget/ar.lproj/InfoPlist.strings
Normal file
@ -0,0 +1 @@
|
|||||||
|
"CFBundleDisplayName" = "الأشخاص";
|
1
Telegram/LegacyWidget/de.lproj/InfoPlist.strings
Normal file
1
Telegram/LegacyWidget/de.lproj/InfoPlist.strings
Normal file
@ -0,0 +1 @@
|
|||||||
|
"CFBundleDisplayName" = "Leute";
|
1
Telegram/LegacyWidget/en.lproj/InfoPlist.strings
Normal file
1
Telegram/LegacyWidget/en.lproj/InfoPlist.strings
Normal file
@ -0,0 +1 @@
|
|||||||
|
"CFBundleDisplayName" = "People";
|
2
Telegram/LegacyWidget/en.lproj/Localizable.strings
Normal file
2
Telegram/LegacyWidget/en.lproj/Localizable.strings
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
"Widget.NoUsers" = "No users here yet...";
|
||||||
|
"Widget.AuthRequired" = "Open Telegram and log in.";
|
1
Telegram/LegacyWidget/es.lproj/InfoPlist.strings
Normal file
1
Telegram/LegacyWidget/es.lproj/InfoPlist.strings
Normal file
@ -0,0 +1 @@
|
|||||||
|
"CFBundleDisplayName" = "Personas";
|
1
Telegram/LegacyWidget/it.lproj/InfoPlist.strings
Normal file
1
Telegram/LegacyWidget/it.lproj/InfoPlist.strings
Normal file
@ -0,0 +1 @@
|
|||||||
|
"CFBundleDisplayName" = "Persone";
|
1
Telegram/LegacyWidget/ko.lproj/InfoPlist.strings
Normal file
1
Telegram/LegacyWidget/ko.lproj/InfoPlist.strings
Normal file
@ -0,0 +1 @@
|
|||||||
|
"CFBundleDisplayName" = "사람";
|
1
Telegram/LegacyWidget/nl.lproj/InfoPlist.strings
Normal file
1
Telegram/LegacyWidget/nl.lproj/InfoPlist.strings
Normal file
@ -0,0 +1 @@
|
|||||||
|
"CFBundleDisplayName" = "Mensen";
|
1
Telegram/LegacyWidget/pt.lproj/InfoPlist.strings
Normal file
1
Telegram/LegacyWidget/pt.lproj/InfoPlist.strings
Normal file
@ -0,0 +1 @@
|
|||||||
|
"CFBundleDisplayName" = "Pessoas";
|
1
Telegram/LegacyWidget/ru.lproj/InfoPlist.strings
Normal file
1
Telegram/LegacyWidget/ru.lproj/InfoPlist.strings
Normal file
@ -0,0 +1 @@
|
|||||||
|
"CFBundleDisplayName" = "Люди";
|
@ -1,8 +0,0 @@
|
|||||||
import Foundation
|
|
||||||
import UserNotifications
|
|
||||||
|
|
||||||
@available(iOSApplicationExtension 10.0, *)
|
|
||||||
@objc(NotificationService)
|
|
||||||
public final class NotificationService: UNNotificationServiceExtension {
|
|
||||||
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user