You've already forked hotpocket
BTHLABS-58: Share Extension in Apple Apps
This commit is contained in:
@@ -7,6 +7,10 @@
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@class HPAuthFlow;
|
||||
|
||||
@interface AppDelegate : UIResponder <UIApplicationDelegate>
|
||||
|
||||
@property (strong, nonnull) HPAuthFlow *authFlow;
|
||||
|
||||
@end
|
||||
|
||||
@@ -7,14 +7,17 @@
|
||||
|
||||
#import "AppDelegate.h"
|
||||
|
||||
#import "HPAuthFlow.h"
|
||||
|
||||
@implementation AppDelegate
|
||||
|
||||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
|
||||
// Override point for customization after application launch.
|
||||
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
|
||||
self.authFlow = [[HPAuthFlow alloc] init];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options {
|
||||
-(UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options {
|
||||
return [[UISceneConfiguration alloc] initWithName:@"Default Configuration" sessionRole:connectingSceneSession.role];
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
//
|
||||
// AuthorizationProgressViewController.h
|
||||
// HotPocket (iOS)
|
||||
//
|
||||
// Created by Tomek Wójcik on 25/09/2025.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface AuthorizationProgressViewController : UIViewController
|
||||
|
||||
@property IBOutlet UIActivityIndicatorView *progressIndicator;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,74 @@
|
||||
//
|
||||
// AuthorizationProgressViewController.m
|
||||
// HotPocket (iOS)
|
||||
//
|
||||
// Created by Tomek Wójcik on 25/09/2025.
|
||||
//
|
||||
|
||||
#import "AuthorizationProgressViewController.h"
|
||||
|
||||
#import "AppDelegate.h"
|
||||
#import "HPCredentialsHelper.h"
|
||||
|
||||
@interface AuthorizationProgressViewController (AuthorizationProgressViewControllerPrivate)
|
||||
|
||||
#pragma mark - Private interface
|
||||
|
||||
@end
|
||||
|
||||
@implementation AuthorizationProgressViewController
|
||||
|
||||
#pragma mark - View lifecycle
|
||||
|
||||
-(void)viewDidLoad {
|
||||
[super viewDidLoad];
|
||||
}
|
||||
|
||||
-(void)viewWillAppear:(BOOL)animated {
|
||||
[super viewWillAppear:animated];
|
||||
[self.progressIndicator startAnimating];
|
||||
|
||||
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAuthFlowDidFinish:) name:@"AuthFlowDidFinish" object:appDelegate.authFlow];
|
||||
}
|
||||
|
||||
-(void)viewWillDisappear:(BOOL)animated {
|
||||
[super viewWillDisappear:animated];
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
}
|
||||
|
||||
-(void)viewDidDisappear:(BOOL)animated {
|
||||
[super viewDidDisappear:animated];
|
||||
[self.progressIndicator stopAnimating];
|
||||
}
|
||||
|
||||
#pragma mark - Notification handlers
|
||||
|
||||
-(void)onAuthFlowDidFinish:(NSNotification *)notification {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
#ifdef DEBUG
|
||||
NSLog(@"-[AuthorizationViewController onAuthFlowDidFinish:] notification=`%@`", notification);
|
||||
#endif
|
||||
HPCredentials *credentials = [[HPCredentialsHelper sharedHelper] getCredentials];
|
||||
|
||||
if (credentials.usable == NO) {
|
||||
UIAlertController *alert = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Oops!", @"Oops!")
|
||||
message:NSLocalizedString(@"HotPocket couldn't complete this operation.", @"HotPocket couldn't complete this operation.")
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
|
||||
[alert addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"Oh well", @"Oh well")
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction *action) {
|
||||
[alert dismissViewControllerAnimated:YES completion:^{
|
||||
[self.navigationController popViewControllerAnimated:YES];
|
||||
}];
|
||||
}]];
|
||||
|
||||
[self presentViewController:alert animated:YES completion:nil];
|
||||
} else {
|
||||
[self.navigationController popToRootViewControllerAnimated:YES];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@end
|
||||
22
services/apple/iOS (App)/AuthorizationViewController.h
Normal file
22
services/apple/iOS (App)/AuthorizationViewController.h
Normal file
@@ -0,0 +1,22 @@
|
||||
//
|
||||
// AuthorizationViewController.h
|
||||
// HotPocket (iOS)
|
||||
//
|
||||
// Created by Tomek Wójcik on 25/09/2025.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface AuthorizationViewController : UIViewController
|
||||
|
||||
@property UIImageView *invalidURLWarningView;
|
||||
|
||||
@property IBOutlet UITextField *instanceURLField;
|
||||
|
||||
-(IBAction)doStartAuthorizationFlow:(id)sender;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
105
services/apple/iOS (App)/AuthorizationViewController.m
Normal file
105
services/apple/iOS (App)/AuthorizationViewController.m
Normal file
@@ -0,0 +1,105 @@
|
||||
//
|
||||
// AuthorizationViewController.m
|
||||
// HotPocket (iOS)
|
||||
//
|
||||
// Created by Tomek Wójcik on 25/09/2025.
|
||||
//
|
||||
|
||||
#import "AuthorizationViewController.h"
|
||||
|
||||
#import "AppDelegate.h"
|
||||
#import "AuthorizationProgressViewController.h"
|
||||
#import "HPAuthFlow.h"
|
||||
#import "HPCredentialsHelper.h"
|
||||
#import "MainViewController.h"
|
||||
#import "NSURL+HotPocketExtensions.h"
|
||||
|
||||
@interface AuthorizationViewController (AuthorizationViewControllerPrivate)
|
||||
|
||||
#pragma mark - Private interface
|
||||
|
||||
@end
|
||||
|
||||
@implementation AuthorizationViewController
|
||||
|
||||
#pragma mark - View lifecycle
|
||||
|
||||
-(void)viewDidLoad {
|
||||
[super viewDidLoad];
|
||||
|
||||
self.invalidURLWarningView = [[UIImageView alloc] initWithImage:[UIImage systemImageNamed:@"exclamationmark.circle.fill"]];
|
||||
self.invalidURLWarningView.contentMode = UIViewContentModeScaleAspectFit;
|
||||
self.invalidURLWarningView.frame = CGRectMake(0, 0, 16, 16);
|
||||
self.invalidURLWarningView.tintColor = [UIColor colorNamed:@"WarningColor"];
|
||||
[self.view addSubview:self.invalidURLWarningView];
|
||||
}
|
||||
|
||||
-(void)viewWillAppear:(BOOL)animated {
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
self.instanceURLField.rightView = self.invalidURLWarningView;
|
||||
self.instanceURLField.rightViewMode = UITextFieldViewModeNever;
|
||||
|
||||
[self.instanceURLField addTarget:self action:@selector(onInstanceURLFieldChanged:) forControlEvents:UIControlEventEditingChanged];
|
||||
}
|
||||
|
||||
#pragma mark - Actions
|
||||
|
||||
-(IBAction)doStartAuthorizationFlow:(id)sender {
|
||||
#ifdef DEBUG
|
||||
NSLog(@"-[AuthorizationViewController doStartAuthorizationFlow:] instanceURL=`%@`", self.instanceURLField.text);
|
||||
#endif
|
||||
if (!self.instanceURLField.text) {
|
||||
// ???
|
||||
return;
|
||||
}
|
||||
|
||||
NSURL *instanceURL = [NSURL URLWithString:self.instanceURLField.text];
|
||||
if (instanceURL.isUsableInHotPocket == NO) {
|
||||
// ???
|
||||
return;
|
||||
}
|
||||
|
||||
UIApplication *application = [UIApplication sharedApplication];
|
||||
AppDelegate *appDeleate = [application delegate];
|
||||
appDeleate.authFlow.baseURL = instanceURL;
|
||||
|
||||
NSURL *authURL = [appDeleate.authFlow start];
|
||||
if (authURL == nil) {
|
||||
// ???
|
||||
return;
|
||||
}
|
||||
|
||||
if ([application canOpenURL:authURL] == YES) {
|
||||
[application openURL:authURL options:@{} completionHandler:^(BOOL result) {
|
||||
if (result == YES) {
|
||||
AuthorizationProgressViewController *authorizationProgressViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"AuthorizationProgressViewController"];
|
||||
[self.navigationController pushViewController:authorizationProgressViewController animated:YES];
|
||||
}
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Event handlers
|
||||
|
||||
-(void)onInstanceURLFieldChanged:(UITextField *)sender {
|
||||
sender.rightViewMode = UITextFieldViewModeNever;
|
||||
|
||||
if (!sender.text || [@"" isEqualToString:sender.text]) {
|
||||
sender.rightViewMode = UITextFieldViewModeAlways;
|
||||
return;
|
||||
}
|
||||
|
||||
NSURL *url = [NSURL URLWithString:sender.text];
|
||||
if (url == nil) {
|
||||
sender.rightViewMode = UITextFieldViewModeAlways;
|
||||
return;
|
||||
}
|
||||
|
||||
if (url.isUsableInHotPocket == NO) {
|
||||
sender.rightViewMode = UITextFieldViewModeAlways;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="23727" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="24127" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
|
||||
<device id="retina6_12" orientation="portrait" appearance="light"/>
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23721"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="24063"/>
|
||||
<capability name="Image references" minToolsVersion="12.0"/>
|
||||
<capability name="Named colors" minToolsVersion="9.0"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
@@ -17,11 +17,24 @@
|
||||
<rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="6HG-Um-bch">
|
||||
<rect key="frame" x="131" y="363" width="128" height="128"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||
<imageReference key="image" image="LargeIcon"/>
|
||||
</imageView>
|
||||
<view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="H2q-Qq-Nf1">
|
||||
<rect key="frame" x="16" y="344" width="361" height="165"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||
<subviews>
|
||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="6HG-Um-bch">
|
||||
<rect key="frame" x="116" y="0.0" width="128" height="128"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<imageReference key="image" image="icon-mac-384.png"/>
|
||||
</imageView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="HotPocket by BTHLabs" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="v6f-dw-6WO">
|
||||
<rect key="frame" x="0.0" y="136" width="361" height="29"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="24"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
</view>
|
||||
</subviews>
|
||||
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
|
||||
<color key="backgroundColor" name="BackgroundColor"/>
|
||||
@@ -29,11 +42,11 @@
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="53" y="375"/>
|
||||
<point key="canvasLocation" x="52.671755725190835" y="374.64788732394368"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
<resources>
|
||||
<image name="LargeIcon" width="128" height="128"/>
|
||||
<image name="icon-mac-384.png" width="384" height="384"/>
|
||||
<namedColor name="BackgroundColor">
|
||||
<color red="0.12941176470588237" green="0.14509803921568629" blue="0.16078431372549021" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</namedColor>
|
||||
|
||||
@@ -1,46 +1,245 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="23727" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="24127" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="7Sa-RR-xgc">
|
||||
<device id="retina6_1" orientation="portrait" appearance="light"/>
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23721"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="24063"/>
|
||||
<capability name="Image references" minToolsVersion="12.0"/>
|
||||
<capability name="Named colors" minToolsVersion="9.0"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--View Controller-->
|
||||
<!--Main View Controller-->
|
||||
<scene sceneID="tne-QT-ifu">
|
||||
<objects>
|
||||
<viewController id="BYZ-38-t0r" customClass="ViewController" sceneMemberID="viewController">
|
||||
<viewController storyboardIdentifier="MainViewController" id="BYZ-38-t0r" customClass="MainViewController" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<wkWebView contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="RDB-ib-igF">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" name="BackgroundColor"/>
|
||||
<wkWebViewConfiguration key="configuration">
|
||||
<audiovisualMediaTypes key="mediaTypesRequiringUserActionForPlayback" none="YES"/>
|
||||
<wkPreferences key="preferences"/>
|
||||
</wkWebViewConfiguration>
|
||||
</wkWebView>
|
||||
<view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Tdb-RK-EKV">
|
||||
<rect key="frame" x="20" y="96" width="374" height="165"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||
<subviews>
|
||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="57V-kg-4Nx">
|
||||
<rect key="frame" x="122" y="0.0" width="128" height="128"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<imageReference key="image" image="icon-mac-384.png"/>
|
||||
</imageView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="HotPocket by BTHLabs" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="cP6-uT-Hh4">
|
||||
<rect key="frame" x="0.0" y="136" width="374" height="29"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="24"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
</view>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="HotPocket is configured and ready." textAlignment="natural" lineBreakMode="wordWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ltc-Em-W9y" customClass="MultilineLabel">
|
||||
<rect key="frame" x="20" y="277" width="374" height="64"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Instance URL" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="GYw-2b-qGS">
|
||||
<rect key="frame" x="20" y="349" width="374" height="21"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="leading" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="OPO-AY-zgd">
|
||||
<rect key="frame" x="20" y="378" width="374" height="35"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
|
||||
<inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
|
||||
<buttonConfiguration key="configuration" style="gray" title="DO NOT LOCALIZE">
|
||||
<color key="baseForegroundColor" name="SecondaryColor"/>
|
||||
</buttonConfiguration>
|
||||
<connections>
|
||||
<action selector="doOpenInstanceURL:" destination="BYZ-38-t0r" eventType="primaryActionTriggered" id="5SW-3o-wiJ"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="wQZ-n6-b0o">
|
||||
<rect key="frame" x="161" y="431" width="92" height="35"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<buttonConfiguration key="configuration" style="gray" title="Log out">
|
||||
<color key="baseForegroundColor" name="DangerColor"/>
|
||||
</buttonConfiguration>
|
||||
<connections>
|
||||
<action selector="doLogOut:" destination="BYZ-38-t0r" eventType="primaryActionTriggered" id="iq7-wK-GMu"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
|
||||
<color key="backgroundColor" name="BackgroundColor"/>
|
||||
<color key="tintColor" name="AccentColor"/>
|
||||
</view>
|
||||
<navigationItem key="navigationItem" id="w8s-f0-7E0"/>
|
||||
<connections>
|
||||
<outlet property="webView" destination="RDB-ib-igF" id="avx-RC-qRB"/>
|
||||
<outlet property="instanceURLButton" destination="OPO-AY-zgd" id="1Wr-H9-eZ6"/>
|
||||
<outlet property="logoutButton" destination="wQZ-n6-b0o" id="vco-vP-zvy"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="53" y="375"/>
|
||||
<point key="canvasLocation" x="962.31884057971024" y="375"/>
|
||||
</scene>
|
||||
<!--Authorization View Controller-->
|
||||
<scene sceneID="zfn-5m-i4Y">
|
||||
<objects>
|
||||
<viewController storyboardIdentifier="AuthorizationViewController" id="1Il-xJ-X5Y" customClass="AuthorizationViewController" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="gKn-cL-a2b">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Kkk-cr-Leu">
|
||||
<rect key="frame" x="20" y="96" width="374" height="165"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||
<subviews>
|
||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="YXT-lU-mHV">
|
||||
<rect key="frame" x="122" y="0.0" width="128" height="128"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<imageReference key="image" image="icon-mac-384.png"/>
|
||||
</imageView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="HotPocket by BTHLabs" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="hhk-23-s8H">
|
||||
<rect key="frame" x="0.0" y="136" width="374" height="29"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="24"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
</view>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Instance URL" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="alG-Ve-nxN">
|
||||
<rect key="frame" x="20" y="277" width="374" height="21"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<textField opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="248" fixedFrame="YES" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="v5s-Uh-qWU" customClass="InstanceURLField">
|
||||
<rect key="frame" x="20" y="306" width="374" height="34"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
|
||||
<color key="backgroundColor" white="0.33333333333333331" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||
<textInputTraits key="textInputTraits" autocorrectionType="no" spellCheckingType="no" keyboardType="URL" returnKeyType="go" smartDashesType="no" smartInsertDeleteType="no" smartQuotesType="no" textContentType="url"/>
|
||||
<connections>
|
||||
<action selector="doStartAuthorizationFlow:" destination="1Il-xJ-X5Y" eventType="primaryActionTriggered" id="Rd9-1f-N6Z"/>
|
||||
</connections>
|
||||
</textField>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Enter the URL to your HotPocket instance, e.g. https://my.hotpocket.app" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Tn1-fl-daL" customClass="MultilineLabel">
|
||||
<rect key="frame" x="20" y="348" width="374" height="64"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="eKt-N1-DEJ">
|
||||
<rect key="frame" x="20" y="428" width="374" height="35"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
|
||||
<state key="normal" title="Button"/>
|
||||
<buttonConfiguration key="configuration" style="filled" title="Continue"/>
|
||||
<connections>
|
||||
<action selector="doStartAuthorizationFlow:" destination="1Il-xJ-X5Y" eventType="primaryActionTriggered" id="U0V-Pp-M2x"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<viewLayoutGuide key="safeArea" id="dL2-4T-yXY"/>
|
||||
<color key="backgroundColor" name="BackgroundColor"/>
|
||||
<color key="tintColor" name="AccentColor"/>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="instanceURLField" destination="v5s-Uh-qWU" id="hRQ-r8-3Dz"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="m6b-Bm-Ty7" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="1726.0869565217392" y="375"/>
|
||||
</scene>
|
||||
<!--Navigation Controller-->
|
||||
<scene sceneID="zFJ-kU-27j">
|
||||
<objects>
|
||||
<navigationController automaticallyAdjustsScrollViewInsets="NO" id="7Sa-RR-xgc" sceneMemberID="viewController">
|
||||
<toolbarItems/>
|
||||
<navigationBar key="navigationBar" contentMode="scaleToFill" id="PrZ-Cz-0b5">
|
||||
<rect key="frame" x="0.0" y="96" width="414" height="54"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</navigationBar>
|
||||
<nil name="viewControllers"/>
|
||||
<connections>
|
||||
<segue destination="BYZ-38-t0r" kind="relationship" relationship="rootViewController" id="7mY-Zh-QsC"/>
|
||||
</connections>
|
||||
</navigationController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="GIS-z2-loC" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="52.173913043478265" y="375"/>
|
||||
</scene>
|
||||
<!--Authorization Progress View Controller-->
|
||||
<scene sceneID="689-0y-Gyr">
|
||||
<objects>
|
||||
<viewController storyboardIdentifier="AuthorizationProgressViewController" id="aiy-3v-nI7" customClass="AuthorizationProgressViewController" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="ljp-b5-lta">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="wKr-WU-Iec">
|
||||
<rect key="frame" x="20" y="96" width="374" height="165"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||
<subviews>
|
||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="v6u-sE-tzJ">
|
||||
<rect key="frame" x="122" y="0.0" width="128" height="128"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<imageReference key="image" image="icon-mac-384.png"/>
|
||||
</imageView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="HotPocket by BTHLabs" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="50v-cp-DGd">
|
||||
<rect key="frame" x="0.0" y="136" width="374" height="29"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="24"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
</view>
|
||||
<activityIndicatorView opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" fixedFrame="YES" style="whiteLarge" translatesAutoresizingMaskIntoConstraints="NO" id="DNy-gf-n60">
|
||||
<rect key="frame" x="189" y="306" width="37" height="37"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
</activityIndicatorView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Awaiting authentication response..." textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="qiJ-yx-nMd">
|
||||
<rect key="frame" x="20" y="359" width="374" height="21"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<viewLayoutGuide key="safeArea" id="zyd-wv-1rn"/>
|
||||
<color key="backgroundColor" name="BackgroundColor"/>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="progressIndicator" destination="DNy-gf-n60" id="hJF-jc-ZJ0"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="N3D-cM-5Ro" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="2532" y="375"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
<color key="tintColor" name="AccentColor"/>
|
||||
<resources>
|
||||
<image name="icon-mac-384.png" width="384" height="384"/>
|
||||
<namedColor name="AccentColor">
|
||||
<color red="0.10980392156862745" green="0.72941176470588232" blue="0.92941176470588238" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</namedColor>
|
||||
<namedColor name="BackgroundColor">
|
||||
<color red="0.12941176470588237" green="0.14509803921568629" blue="0.16078431372549021" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</namedColor>
|
||||
<namedColor name="DangerColor">
|
||||
<color red="0.93300002813339233" green="0.3919999897480011" blue="0.46299999952316284" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</namedColor>
|
||||
<namedColor name="SecondaryColor">
|
||||
<color red="0.0" green="0.50980392156862742" blue="0.8666666666666667" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</namedColor>
|
||||
</resources>
|
||||
</document>
|
||||
|
||||
15
services/apple/iOS (App)/HotPocket (iOS).entitlements
Normal file
15
services/apple/iOS (App)/HotPocket (iOS).entitlements
Normal file
@@ -0,0 +1,15 @@
|
||||
<?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.pl.bthlabs.HotPocket</string>
|
||||
</array>
|
||||
<key>keychain-access-groups</key>
|
||||
<array>
|
||||
<string>$(AppIdentifierPrefix)pl.bthlabs.HotPocketShared</string>
|
||||
<string>$(AppIdentifierPrefix)pl.bthlabs.HotPocket</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -2,6 +2,32 @@
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Viewer</string>
|
||||
<key>CFBundleURLIconFile</key>
|
||||
<string>icon-mac-384</string>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>HotPocketDesktopMac</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>hotpocket-mobile</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
<key>HPAuthFlowPostAuthenticateURLParts</key>
|
||||
<dict>
|
||||
<key>host</key>
|
||||
<string>post-authenticate</string>
|
||||
<key>scheme</key>
|
||||
<string>hotpocket-mobile</string>
|
||||
</dict>
|
||||
<key>HPAuthFlowSource</key>
|
||||
<string>HotPocketMobile</string>
|
||||
<key>HPRPCClientOrigin</key>
|
||||
<string>hotpocket-mobile://HPRPCClient</string>
|
||||
<key>UIApplicationSceneManifest</key>
|
||||
<dict>
|
||||
<key>UIApplicationSupportsMultipleScenes</key>
|
||||
|
||||
16
services/apple/iOS (App)/InstanceURLField.h
Normal file
16
services/apple/iOS (App)/InstanceURLField.h
Normal file
@@ -0,0 +1,16 @@
|
||||
//
|
||||
// InstanceURLField.h
|
||||
// HotPocket (macOS)
|
||||
//
|
||||
// Created by Tomek Wójcik on 30/09/2025.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface InstanceURLField : UITextField
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
21
services/apple/iOS (App)/InstanceURLField.m
Normal file
21
services/apple/iOS (App)/InstanceURLField.m
Normal file
@@ -0,0 +1,21 @@
|
||||
//
|
||||
// InstanceURLField.m
|
||||
// HotPocket (macOS)
|
||||
//
|
||||
// Created by Tomek Wójcik on 30/09/2025.
|
||||
//
|
||||
|
||||
#import "InstanceURLField.h"
|
||||
|
||||
@implementation InstanceURLField
|
||||
|
||||
-(CGRect)rightViewRectForBounds:(CGRect)bounds {
|
||||
if (self.rightViewMode != UITextFieldViewModeNever) {
|
||||
CGFloat offsetTop = (bounds.size.height - 16.0) / 2.0;
|
||||
return CGRectMake(bounds.size.width - 16.0 - offsetTop, offsetTop, 16.0, 16.0);
|
||||
}
|
||||
|
||||
return CGRectNull;
|
||||
}
|
||||
|
||||
@end
|
||||
22
services/apple/iOS (App)/MainViewController.h
Normal file
22
services/apple/iOS (App)/MainViewController.h
Normal file
@@ -0,0 +1,22 @@
|
||||
//
|
||||
// MainViewController.h
|
||||
// HotPocket (iOS)
|
||||
//
|
||||
// Created by Tomek Wójcik on 25/09/2025.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface MainViewController : UIViewController
|
||||
|
||||
@property IBOutlet UIButton *instanceURLButton;
|
||||
@property IBOutlet UIButton *logoutButton;
|
||||
|
||||
-(IBAction)doOpenInstanceURL:(id)sender;
|
||||
-(IBAction)doLogOut:(id)sender;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
77
services/apple/iOS (App)/MainViewController.m
Normal file
77
services/apple/iOS (App)/MainViewController.m
Normal file
@@ -0,0 +1,77 @@
|
||||
//
|
||||
// MainViewController.m
|
||||
// HotPocket (iOS)
|
||||
//
|
||||
// Created by Tomek Wójcik on 25/09/2025.
|
||||
//
|
||||
|
||||
#import "MainViewController.h"
|
||||
|
||||
#import "HPCredentialsHelper.h"
|
||||
|
||||
#import "AuthorizationViewController.h"
|
||||
|
||||
@interface MainViewController (MainViewControllerPrivate)
|
||||
|
||||
#pragma mark - Private interface
|
||||
|
||||
@end
|
||||
|
||||
@implementation MainViewController
|
||||
|
||||
#pragma mark - View lifecycle
|
||||
|
||||
-(void)viewDidLoad {
|
||||
[super viewDidLoad];
|
||||
|
||||
[self.instanceURLButton setTitle:@"" forState:UIControlStateNormal];
|
||||
self.instanceURLButton.enabled = NO;
|
||||
|
||||
self.logoutButton.enabled = NO;
|
||||
}
|
||||
|
||||
-(void)viewWillAppear:(BOOL)animated {
|
||||
[super viewWillAppear:animated];
|
||||
[self.navigationController setNavigationBarHidden:YES animated:NO];
|
||||
|
||||
HPCredentials *credentials = [[HPCredentialsHelper sharedHelper] getCredentials];
|
||||
if (credentials.usable == NO) {
|
||||
AuthorizationViewController *authorizationViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"AuthorizationViewController"];
|
||||
[self.navigationController pushViewController:authorizationViewController animated:NO];
|
||||
} else {
|
||||
[self.instanceURLButton setTitle:credentials.baseURL forState:UIControlStateNormal];
|
||||
self.instanceURLButton.enabled = YES;
|
||||
|
||||
self.logoutButton.enabled = YES;
|
||||
}
|
||||
|
||||
NSString *instanceURLText = @"";
|
||||
if (credentials.baseURL != nil) {
|
||||
instanceURLText = credentials.baseURL;
|
||||
}
|
||||
|
||||
self.instanceURLButton.titleLabel.text = instanceURLText;
|
||||
}
|
||||
|
||||
#pragma mark - Actions
|
||||
|
||||
-(IBAction)doOpenInstanceURL:(id)sender {
|
||||
HPCredentials *credentials = [[HPCredentialsHelper sharedHelper] getCredentials];
|
||||
if (credentials.usable == YES) {
|
||||
NSURL *instanceURL = [NSURL URLWithString:credentials.baseURL];
|
||||
|
||||
UIApplication *application = [UIApplication sharedApplication];
|
||||
if ([application canOpenURL:instanceURL] == YES) {
|
||||
[application openURL:instanceURL options:@{} completionHandler:nil];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-(IBAction)doLogOut:(id)sender {
|
||||
[[HPCredentialsHelper sharedHelper] clearCredentials];
|
||||
|
||||
AuthorizationViewController *authorizationViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"AuthorizationViewController"];
|
||||
[self.navigationController pushViewController:authorizationViewController animated:NO];
|
||||
}
|
||||
|
||||
@end
|
||||
16
services/apple/iOS (App)/MultilineLabel.h
Normal file
16
services/apple/iOS (App)/MultilineLabel.h
Normal file
@@ -0,0 +1,16 @@
|
||||
//
|
||||
// MultilineLabel.h
|
||||
// HotPocket (iOS)
|
||||
//
|
||||
// Created by Tomek Wójcik on 25/09/2025.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface MultilineLabel : UILabel
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
24
services/apple/iOS (App)/MultilineLabel.m
Normal file
24
services/apple/iOS (App)/MultilineLabel.m
Normal file
@@ -0,0 +1,24 @@
|
||||
//
|
||||
// MultilineLabel.m
|
||||
// HotPocket (iOS)
|
||||
//
|
||||
// Created by Tomek Wójcik on 25/09/2025.
|
||||
//
|
||||
|
||||
#import "MultilineLabel.h"
|
||||
|
||||
@implementation MultilineLabel
|
||||
|
||||
-(void)drawTextInRect:(CGRect)rect {
|
||||
if (!self.text) {
|
||||
[super drawTextInRect:rect];
|
||||
return;
|
||||
}
|
||||
|
||||
CGSize textSize = [self sizeThatFits:CGSizeMake(rect.size.width, CGFLOAT_MAX)];
|
||||
CGRect textRect = CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, MIN(rect.size.height, textSize.height));
|
||||
|
||||
[super drawTextInRect:textRect];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -7,6 +7,24 @@
|
||||
|
||||
#import "SceneDelegate.h"
|
||||
|
||||
#import "AppDelegate.h"
|
||||
#import "HPAuthFlow.h"
|
||||
|
||||
@implementation SceneDelegate
|
||||
|
||||
-(void)scene:(UIScene *)scene openURLContexts:(NSSet<UIOpenURLContext *> *)URLContexts {
|
||||
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
|
||||
|
||||
for (UIOpenURLContext *context in URLContexts) {
|
||||
NSURL *url = context.URL;
|
||||
HPAuthParams *receivedAuthParams = [appDelegate.authFlow handlePostAuthenticateURL:url];
|
||||
|
||||
if (receivedAuthParams == nil) {
|
||||
return;
|
||||
}
|
||||
|
||||
[appDelegate.authFlow handleAuthParams:receivedAuthParams];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Reference in New Issue
Block a user