Commit d6cbff22 authored by Vincent L. Cone's avatar Vincent L. Cone Committed by Felix Paul Kühne

iOS: major refactoring of network login view

- Add support for addition login fields

- Split responsibilities
Signed-off-by: Felix Paul Kühne's avatarFelix Paul Kühne <fkuehne@videolan.org>
parent bb9fb5a6
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="9059" systemVersion="15B42" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="10116" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<deployment identifier="iOS"/>
<development version="5000" identifier="xcode"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9049"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="VLCNetworkLoginViewController">
<connections>
<outlet property="connectButton" destination="6" id="96"/>
<outlet property="loginHelpLabel" destination="lGc-Rk-dDO" id="q9y-NH-Vuw"/>
<outlet property="passwordField" destination="94" id="98"/>
<outlet property="portField" destination="apI-bG-FZ2" id="MIF-Oo-nwz"/>
<outlet property="portLabel" destination="Zhl-CE-wU8" id="zn0-t5-T93"/>
<outlet property="protocolSegmentedControl" destination="NYh-cy-I1V" id="ceN-Fw-Wvi"/>
<outlet property="saveButton" destination="axZ-sK-2Iz" id="V1h-25-LcT"/>
<outlet property="serverField" destination="7" id="1wI-tJ-SsR"/>
<outlet property="serverLabel" destination="LPm-mG-2Dr" id="wuB-QJ-2n3"/>
<outlet property="storedServersTableView" destination="105" id="spe-O0-i8M"/>
<outlet property="usernameField" destination="44" id="101"/>
<outlet property="tableView" destination="105" id="PqC-Fu-pfy"/>
<outlet property="view" destination="1" id="3"/>
</connections>
</placeholder>
......@@ -31,167 +21,20 @@
<userLayoutGuide location="160" affinity="minX"/>
</userGuides>
<subviews>
<textField clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="yourserver.local" textAlignment="center" minimumFontSize="17" clearButtonMode="unlessEditing" translatesAutoresizingMaskIntoConstraints="NO" id="7">
<rect key="frame" x="104" y="44" width="216" height="31"/>
<animations/>
<color key="backgroundColor" red="0.28627450980392155" green="0.28627450980392155" blue="0.28627450980392155" alpha="1" colorSpace="calibratedRGB"/>
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<textInputTraits key="textInputTraits" autocorrectionType="no" keyboardAppearance="alert"/>
</textField>
<button contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="6">
<rect key="frame" x="0.0" y="122" width="320" height="40"/>
<animations/>
<color key="backgroundColor" white="0.0" alpha="1" colorSpace="calibratedWhite"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
<state key="normal" title="Connect"/>
<connections>
<action selector="connectToServer:" destination="-1" eventType="touchUpInside" id="104"/>
</connections>
</button>
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" showsVerticalScrollIndicator="NO" style="plain" separatorStyle="none" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" translatesAutoresizingMaskIntoConstraints="NO" id="105">
<rect key="frame" x="0.0" y="330" width="320" height="192"/>
<animations/>
<color key="separatorColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<connections>
<outlet property="dataSource" destination="-1" id="109"/>
<outlet property="delegate" destination="-1" id="108"/>
</connections>
<rect key="frame" x="0.0" y="0.0" width="320" height="522"/>
<color key="separatorColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</tableView>
<button contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="axZ-sK-2Iz">
<rect key="frame" x="0.0" y="282" width="320" height="40"/>
<animations/>
<color key="backgroundColor" white="0.0" alpha="1" colorSpace="calibratedWhite"/>
<constraints>
<constraint firstAttribute="height" constant="40" id="DAp-u8-CTD"/>
</constraints>
<fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
<state key="normal" title="Save"/>
<connections>
<action selector="saveServer:" destination="-1" eventType="touchUpInside" id="ZeK-OS-WaT"/>
</connections>
</button>
<textField clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="Password" textAlignment="center" minimumFontSize="17" clearButtonMode="unlessEditing" translatesAutoresizingMaskIntoConstraints="NO" id="94">
<rect key="frame" x="0.0" y="206" width="320" height="31"/>
<animations/>
<color key="backgroundColor" red="0.28627450980392155" green="0.28627450980392155" blue="0.28627450980392155" alpha="1" colorSpace="calibratedRGB"/>
<constraints>
<constraint firstAttribute="height" constant="31" id="t5J-e3-YiA"/>
</constraints>
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<textInputTraits key="textInputTraits" autocorrectionType="no" keyboardAppearance="alert" secureTextEntry="YES"/>
</textField>
<textField clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="User" textAlignment="center" minimumFontSize="17" clearButtonMode="unlessEditing" translatesAutoresizingMaskIntoConstraints="NO" id="44">
<rect key="frame" x="0.0" y="170" width="320" height="31"/>
<animations/>
<color key="backgroundColor" red="0.28627450980392155" green="0.28627450980392155" blue="0.28627450980392155" alpha="1" colorSpace="calibratedRGB"/>
<constraints>
<constraint firstAttribute="height" constant="31" id="Wcl-En-1Cy"/>
</constraints>
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<textInputTraits key="textInputTraits" autocorrectionType="no" keyboardAppearance="alert"/>
</textField>
<label clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="If required by the server, enter user name and password." textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" minimumFontSize="9" useAutomaticPreferredMaxLayoutWidth="YES" preferredMaxLayoutWidth="304" translatesAutoresizingMaskIntoConstraints="NO" id="lGc-Rk-dDO">
<rect key="frame" x="8" y="243" width="304" height="34"/>
<animations/>
<color key="backgroundColor" red="0.15686274510000001" green="0.15686274510000001" blue="0.15686274510000001" alpha="1" colorSpace="calibratedRGB"/>
<constraints>
<constraint firstAttribute="height" constant="34" id="S0f-AU-sdf"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<color key="textColor" red="0.58823529411764708" green="0.58823529411764708" blue="0.58823529411764708" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
<label clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Port" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" minimumFontSize="9" useAutomaticPreferredMaxLayoutWidth="YES" preferredMaxLayoutWidth="88" translatesAutoresizingMaskIntoConstraints="NO" id="Zhl-CE-wU8">
<rect key="frame" x="8" y="83" width="88" height="31"/>
<animations/>
<color key="backgroundColor" red="0.15686274510000001" green="0.15686274510000001" blue="0.15686274510000001" alpha="1" colorSpace="calibratedRGB"/>
<constraints>
<constraint firstAttribute="width" constant="88" id="p4B-SD-ePV"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<color key="textColor" red="0.58823529409999997" green="0.58823529409999997" blue="0.58823529409999997" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
<segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" translatesAutoresizingMaskIntoConstraints="NO" id="NYh-cy-I1V">
<rect key="frame" x="8" y="8" width="304" height="29"/>
<animations/>
<segments>
<segment title="SMB"/>
<segment title="FTP"/>
<segment title="PLEX"/>
</segments>
<color key="tintColor" white="0.66666666666666663" alpha="1" colorSpace="calibratedWhite"/>
<connections>
<action selector="protocolSelectionChanged:" destination="-1" eventType="touchUpInside" id="X3V-Yt-aLq"/>
<action selector="protocolSelectionChanged:" destination="-1" eventType="valueChanged" id="ngV-iM-5Bw"/>
</connections>
</segmentedControl>
<textField clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="1234" textAlignment="center" minimumFontSize="17" clearButtonMode="unlessEditing" translatesAutoresizingMaskIntoConstraints="NO" id="apI-bG-FZ2">
<rect key="frame" x="104" y="83" width="216" height="31"/>
<animations/>
<color key="backgroundColor" red="0.28627450980000002" green="0.28627450980000002" blue="0.28627450980000002" alpha="1" colorSpace="calibratedRGB"/>
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<textInputTraits key="textInputTraits" autocorrectionType="no" keyboardAppearance="alert"/>
</textField>
<label clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Server" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" minimumFontSize="9" useAutomaticPreferredMaxLayoutWidth="YES" preferredMaxLayoutWidth="88" translatesAutoresizingMaskIntoConstraints="NO" id="LPm-mG-2Dr">
<rect key="frame" x="8" y="44" width="88" height="31"/>
<animations/>
<color key="backgroundColor" red="0.15686274510000001" green="0.15686274510000001" blue="0.15686274510000001" alpha="1" colorSpace="calibratedRGB"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<color key="textColor" red="0.58823529409999997" green="0.58823529409999997" blue="0.58823529409999997" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<animations/>
<color key="backgroundColor" red="0.15686274509803921" green="0.15686274509803921" blue="0.15686274509803921" alpha="1" colorSpace="calibratedRGB"/>
<color key="backgroundColor" red="0.15686274509803921" green="0.15686274509803921" blue="0.15686274509803921" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="94" firstAttribute="leading" secondItem="1" secondAttribute="leading" id="00j-iv-ALs"/>
<constraint firstItem="apI-bG-FZ2" firstAttribute="leading" secondItem="Zhl-CE-wU8" secondAttribute="trailing" constant="8" id="0zc-Ga-gVi"/>
<constraint firstItem="7" firstAttribute="leading" secondItem="LPm-mG-2Dr" secondAttribute="trailing" constant="8" id="1Ih-ZI-DYW"/>
<constraint firstItem="44" firstAttribute="top" secondItem="1" secondAttribute="top" constant="170" id="3ie-b8-6nV"/>
<constraint firstItem="lGc-Rk-dDO" firstAttribute="top" secondItem="94" secondAttribute="bottom" constant="6" id="3qD-yw-3wT"/>
<constraint firstItem="apI-bG-FZ2" firstAttribute="width" secondItem="7" secondAttribute="width" id="5gp-i0-dXn"/>
<constraint firstAttribute="trailing" secondItem="apI-bG-FZ2" secondAttribute="trailing" id="5x5-Qe-7Oy"/>
<constraint firstItem="apI-bG-FZ2" firstAttribute="height" secondItem="7" secondAttribute="height" id="7bL-Mv-jlI"/>
<constraint firstAttribute="trailing" secondItem="6" secondAttribute="trailing" id="AQj-p8-0a0"/>
<constraint firstItem="LPm-mG-2Dr" firstAttribute="top" secondItem="1" secondAttribute="top" constant="44" id="BJg-3H-0vg"/>
<constraint firstAttribute="bottom" secondItem="105" secondAttribute="bottom" id="8a7-I6-Jyi"/>
<constraint firstAttribute="bottom" secondItem="105" secondAttribute="bottom" id="BTW-QM-u2i"/>
<constraint firstItem="7" firstAttribute="top" secondItem="1" secondAttribute="top" constant="44" id="C0R-Jy-w5t"/>
<constraint firstItem="Zhl-CE-wU8" firstAttribute="leading" secondItem="1" secondAttribute="leading" constant="8" id="E71-7V-rsg"/>
<constraint firstItem="NYh-cy-I1V" firstAttribute="leading" secondItem="1" secondAttribute="leading" constant="8" id="Hrm-13-0RW"/>
<constraint firstItem="44" firstAttribute="width" secondItem="94" secondAttribute="width" id="IYR-aa-sG0"/>
<constraint firstItem="apI-bG-FZ2" firstAttribute="height" secondItem="Zhl-CE-wU8" secondAttribute="height" id="Ksd-y3-VET"/>
<constraint firstItem="NYh-cy-I1V" firstAttribute="top" secondItem="1" secondAttribute="top" constant="8" id="LMY-BT-hVj"/>
<constraint firstItem="7" firstAttribute="height" secondItem="LPm-mG-2Dr" secondAttribute="height" id="MO8-O0-UJL"/>
<constraint firstItem="6" firstAttribute="height" secondItem="axZ-sK-2Iz" secondAttribute="height" id="MlF-WG-H0C"/>
<constraint firstItem="7" firstAttribute="top" secondItem="NYh-cy-I1V" secondAttribute="bottom" constant="8" id="OTS-Bf-W5z"/>
<constraint firstItem="44" firstAttribute="height" secondItem="94" secondAttribute="height" id="Oba-Fv-oJH"/>
<constraint firstItem="6" firstAttribute="top" secondItem="1" secondAttribute="top" constant="122" id="Oj4-2C-zHh"/>
<constraint firstItem="6" firstAttribute="width" secondItem="axZ-sK-2Iz" secondAttribute="width" id="Pim-ys-gBx"/>
<constraint firstItem="105" firstAttribute="top" secondItem="axZ-sK-2Iz" secondAttribute="bottom" constant="8" id="To5-Xz-OAh"/>
<constraint firstItem="Zhl-CE-wU8" firstAttribute="top" secondItem="1" secondAttribute="top" constant="83" id="UBS-tC-jyT"/>
<constraint firstItem="44" firstAttribute="leading" secondItem="1" secondAttribute="leading" id="UWi-54-8I3"/>
<constraint firstItem="105" firstAttribute="leading" secondItem="1" secondAttribute="leading" id="HxN-BZ-SIS"/>
<constraint firstAttribute="trailing" secondItem="105" secondAttribute="trailing" id="Vvv-1Z-ZMc"/>
<constraint firstItem="axZ-sK-2Iz" firstAttribute="top" secondItem="lGc-Rk-dDO" secondAttribute="bottom" constant="5" id="Y1m-jA-dqT"/>
<constraint firstItem="105" firstAttribute="top" secondItem="1" secondAttribute="top" id="Xpn-Bx-WkR"/>
<constraint firstItem="105" firstAttribute="leading" secondItem="1" secondAttribute="leading" id="aIE-Wg-5Y7"/>
<constraint firstItem="apI-bG-FZ2" firstAttribute="top" secondItem="1" secondAttribute="top" constant="83" id="cQt-BV-MQb"/>
<constraint firstAttribute="trailing" secondItem="axZ-sK-2Iz" secondAttribute="trailing" id="dgP-As-UCL"/>
<constraint firstItem="LPm-mG-2Dr" firstAttribute="leading" secondItem="1" secondAttribute="leading" constant="8" id="doh-7s-8iS"/>
<constraint firstItem="44" firstAttribute="height" secondItem="apI-bG-FZ2" secondAttribute="height" id="gJO-VL-TaV"/>
<constraint firstItem="6" firstAttribute="leading" secondItem="1" secondAttribute="leading" id="igV-Hl-tye"/>
<constraint firstAttribute="trailing" secondItem="94" secondAttribute="trailing" id="kmd-me-HsS"/>
<constraint firstAttribute="trailing" secondItem="lGc-Rk-dDO" secondAttribute="trailing" constant="8" id="nNt-k2-iyA"/>
<constraint firstAttribute="trailing" secondItem="NYh-cy-I1V" secondAttribute="trailing" constant="8" id="oxC-Xh-glK"/>
<constraint firstItem="44" firstAttribute="height" secondItem="7" secondAttribute="height" id="qQ9-mw-Sk6"/>
<constraint firstAttribute="trailing" secondItem="7" secondAttribute="trailing" id="s6R-j0-C63"/>
<constraint firstAttribute="trailing" secondItem="44" secondAttribute="trailing" id="sh3-sl-Y8t"/>
<constraint firstItem="axZ-sK-2Iz" firstAttribute="leading" secondItem="1" secondAttribute="leading" id="vs0-MA-8BC"/>
<constraint firstItem="lGc-Rk-dDO" firstAttribute="leading" secondItem="1" secondAttribute="leading" constant="8" id="vxv-nw-B8b"/>
<constraint firstItem="94" firstAttribute="top" secondItem="44" secondAttribute="bottom" constant="5" id="wQo-eO-rj9"/>
<constraint firstAttribute="trailing" secondItem="105" secondAttribute="trailing" id="eHn-Wc-T7J"/>
</constraints>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<point key="canvasLocation" x="352" y="366"/>
......
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="10116" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="VLCNetworkLoginViewFieldCellIdentifier" id="tLk-x5-WKT" customClass="VLCNetworkLoginViewFieldCell">
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="tLk-x5-WKT" id="RHc-y8-FAl">
<rect key="frame" x="0.0" y="0.0" width="320" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<view contentMode="scaleToFill" id="n31-ec-rUo">
<rect key="frame" x="0.0" y="1" width="320" height="41.5"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="0.28999999999999998" alpha="1" colorSpace="calibratedWhite"/>
</view>
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" textAlignment="natural" minimumFontSize="17" clearButtonMode="whileEditing" id="63o-Hv-MMw">
<rect key="frame" x="8" y="0.0" width="304" height="44"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<textInputTraits key="textInputTraits"/>
</textField>
</subviews>
</tableViewCellContentView>
<connections>
<outlet property="textField" destination="63o-Hv-MMw" id="B8N-cz-S5I"/>
</connections>
<point key="canvasLocation" x="217" y="466"/>
</tableViewCell>
</objects>
</document>
......@@ -12,6 +12,10 @@
#import "VLCNetworkServerLoginInformation.h"
NS_ASSUME_NONNULL_BEGIN
@interface VLCNetworkServerLoginInformation (Keychain)
@property (nonatomic, readonly) NSString *keychainServiceIdentifier;
+ (instancetype)loginInformationWithKeychainIdentifier:(NSString *)keychainIdentifier;
- (BOOL)loadLoginInformationFromKeychainWithError:(NSError * _Nullable __autoreleasing *)error;
- (BOOL)saveLoginInformationToKeychainWithError:(NSError * _Nullable __autoreleasing *)error;
- (BOOL)deleteFromKeychainWithError:(NSError * _Nullable __autoreleasing *)error;
......
......@@ -14,6 +14,17 @@
@implementation VLCNetworkServerLoginInformation (Keychain)
+ (instancetype)loginInformationWithKeychainIdentifier:(NSString *)keychainIdentifier
{
NSURLComponents *components = [NSURLComponents componentsWithString:keychainIdentifier];
VLCNetworkServerLoginInformation *login = [VLCNetworkServerLoginInformation newLoginInformationForProtocol:components.scheme];
login.address = components.host;
login.port = components.port;
return login;
}
- (NSString *)keychainServiceIdentifier
{
NSURLComponents *components = [[NSURLComponents alloc] init];
......
......@@ -15,7 +15,7 @@
NS_ASSUME_NONNULL_BEGIN
@interface VLCNetworkServerLoginInformationField : NSObject <VLCNetworkServerLoginInformationField>
@interface VLCNetworkServerLoginInformationField : NSObject <NSCopying, VLCNetworkServerLoginInformationField>
@property (nonatomic, readonly) VLCNetworkServerLoginInformationFieldType type;
@property (nonatomic, readonly) NSString *identifier;
@property (nonatomic, readonly) NSString *localizedLabel;
......@@ -28,12 +28,15 @@ NS_ASSUME_NONNULL_BEGIN
- (instancetype)init NS_UNAVAILABLE;
@end
@interface VLCNetworkServerLoginInformation : NSObject <VLCNetworkServerLoginInformation>
@interface VLCNetworkServerLoginInformation : NSObject <NSCopying, VLCNetworkServerLoginInformation>
@property (nonatomic, copy, nullable) NSString *username;
@property (nonatomic, copy, nullable) NSString *password;
@property (nonatomic, copy) NSString *address;
@property (nonatomic, copy) NSNumber *port;
@property (nonatomic, copy) NSString *protocolIdentifier;
@property (nonatomic, copy) NSArray<VLCNetworkServerLoginInformationField *> *additionalFields;
+ (instancetype)newLoginInformationForProtocol:(NSString *)protocolIdentifier;
+ (void)registerTemplateLoginInformation:(VLCNetworkServerLoginInformation *)loginInformation;
@end
NS_ASSUME_NONNULL_END
......@@ -26,7 +26,48 @@
return self;
}
- (id)copyWithZone:(NSZone *)zone
{
return [[[self class] allocWithZone:zone] initWithType:self.type identifier:self.identifier label:self.localizedLabel textValue:self.textValue];
}
@end
@implementation VLCNetworkServerLoginInformation
- (id)copyWithZone:(NSZone *)zone
{
VLCNetworkServerLoginInformation *other = [[[self class] allocWithZone:zone] init];
other.username = self.username;
other.password = self.password;
other.address = self.address;
other.port = self.port;
other.protocolIdentifier = self.protocolIdentifier;
other.additionalFields = [[NSMutableArray alloc] initWithArray:self.additionalFields copyItems:YES];
return other;
}
static NSMutableDictionary<NSString *, VLCNetworkServerLoginInformation *> *VLCNetworkServerLoginInformationRegistry = nil;
+ (void)initialize
{
[super initialize];
VLCNetworkServerLoginInformationRegistry = [[NSMutableDictionary alloc] init];
}
+ (void)registerTemplateLoginInformation:(VLCNetworkServerLoginInformation *)loginInformation
{
VLCNetworkServerLoginInformationRegistry[loginInformation.protocolIdentifier] = [loginInformation copy];
}
+ (instancetype)newLoginInformationForProtocol:(NSString *)protocolIdentifier
{
VLCNetworkServerLoginInformation *loginInformation = [VLCNetworkServerLoginInformationRegistry[protocolIdentifier] copy];
if (!loginInformation) {
loginInformation = [[VLCNetworkServerLoginInformation alloc] init];
}
return loginInformation;
}
@end
\ No newline at end of file
......@@ -13,6 +13,10 @@
#import "VLCLocalNetworkServiceBrowserDSM.h"
#import "VLCNetworkServerLoginInformation.h"
@interface VLCLocalNetworkServiceDSM ()
+ (void)registerLoginInformation;
@end
@implementation VLCLocalNetworkServiceBrowserDSM
- (instancetype)init {
......@@ -32,6 +36,12 @@
return nil;
}
+ (void)initialize
{
[super initialize];
[VLCLocalNetworkServiceDSM registerLoginInformation];
}
@end
......@@ -39,6 +49,22 @@ NSString *const VLCNetworkServerProtocolIdentifierSMB = @"smb";
static NSString *const VLCLocalNetworkServiceDSMWorkgroupIdentifier = @"VLCLocalNetworkServiceDSMWorkgroup";
@implementation VLCLocalNetworkServiceDSM
+ (void)registerLoginInformation
{
VLCNetworkServerLoginInformation *login = [[VLCNetworkServerLoginInformation alloc] init];
login.protocolIdentifier = VLCNetworkServerProtocolIdentifierSMB;
VLCNetworkServerLoginInformationField *workgroupField = [[VLCNetworkServerLoginInformationField alloc] initWithType:VLCNetworkServerLoginInformationFieldTypeText
identifier:VLCLocalNetworkServiceDSMWorkgroupIdentifier
label:NSLocalizedString(@"DSM_WORKGROUP", nil)
textValue:@"WORKGROUP"];
login.additionalFields = @[workgroupField];
[VLCNetworkServerLoginInformation registerTemplateLoginInformation:login];
}
- (UIImage *)icon {
return [UIImage imageNamed:@"serverIcon"];
}
......@@ -48,14 +74,8 @@ static NSString *const VLCLocalNetworkServiceDSMWorkgroupIdentifier = @"VLCLocal
if (media.mediaType != VLCMediaTypeDirectory)
return nil;
VLCNetworkServerLoginInformation *login = [[VLCNetworkServerLoginInformation alloc] init];
VLCNetworkServerLoginInformation *login = [VLCNetworkServerLoginInformation newLoginInformationForProtocol:VLCNetworkServerProtocolIdentifierSMB];
login.address = self.mediaItem.url.host;
login.protocolIdentifier = VLCNetworkServerProtocolIdentifierSMB;
VLCNetworkServerLoginInformationField *workgroupField = [[VLCNetworkServerLoginInformationField alloc] initWithType:VLCNetworkServerLoginInformationFieldTypeText
identifier:VLCLocalNetworkServiceDSMWorkgroupIdentifier
label:NSLocalizedString(@"DSM_WORKGROUP", nil)
textValue:@"WORKGROUP"];
login.additionalFields = @[workgroupField];
return login;
}
......
/*****************************************************************************
* VLC for iOS
*****************************************************************************
* Copyright (c) 2016 VideoLAN. All rights reserved.
* $Id$
*
* Authors: Vincent L. Cone <vincent.l.cone # tuta.io>
*
* Refer to the COPYING file of the official project for license.
*****************************************************************************/
#import <Foundation/Foundation.h>
#import "VLCNetworkLoginDataSourceSection.h"
NS_ASSUME_NONNULL_BEGIN
@interface VLCNetworkLoginDataSource : NSObject <UITableViewDataSource, UITableViewDelegate>
@property (nonatomic, copy) NSArray<id<VLCNetworkLoginDataSourceSection>> *dataSources;
- (void)configureWithTableView:(UITableView *)tableView;
@end
NS_ASSUME_NONNULL_END
\ No newline at end of file
/*****************************************************************************
* VLC for iOS
*****************************************************************************
* Copyright (c) 2016 VideoLAN. All rights reserved.
* $Id$
*
* Authors: Vincent L. Cone <vincent.l.cone # tuta.io>
*
* Refer to the COPYING file of the official project for license.
*****************************************************************************/
#import "VLCNetworkLoginDataSource.h"
@implementation VLCNetworkLoginDataSource
- (void)configureWithTableView:(UITableView *)tableView
{
tableView.dataSource = self;
tableView.delegate = self;
[self.dataSources enumerateObjectsUsingBlock:^(id<VLCNetworkLoginDataSourceSection> _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
[obj configureWithTableView:tableView];
}];
}
- (void)setDataSources:(NSArray<id<VLCNetworkLoginDataSourceSection>> *)dataSources
{
_dataSources = [dataSources copy];
[dataSources enumerateObjectsUsingBlock:^(id<VLCNetworkLoginDataSourceSection> _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
obj.sectionIndex = idx;
}];
}
#pragma mark - UITableViewDataSource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return self.dataSources.count;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.dataSources[section] numberOfRowsInTableView:tableView];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
id<VLCNetworkLoginDataSourceSection> dataSource = self.dataSources[indexPath.section];
NSUInteger row = indexPath.row;
NSString *cellIdentifier = [dataSource cellIdentifierForRow:row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
[dataSource configureCell:cell forRow:row];
return cell;
}
#pragma mark - UITableViewDelegate
//- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
//{
// cell.backgroundColor = (indexPath.row % 2 == 0)? [UIColor blackColor]: [UIColor VLCDarkBackgroundColor];
//}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
BOOL editable = YES;
id<VLCNetworkLoginDataSourceSection> dataSource = self.dataSources[indexPath.section];
if ([dataSource respondsToSelector:@selector(canEditRow:)]) {
editable = [dataSource canEditRow:indexPath.row];
}
return editable;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
id<VLCNetworkLoginDataSourceSection> dataSource = self.dataSources[indexPath.section];
if ([dataSource respondsToSelector:@selector(commitEditingStyle:forRow:)]) {
[dataSource commitEditingStyle:editingStyle forRow:indexPath.row];
}
}
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSIndexPath *targetIndexPath = indexPath;
id<VLCNetworkLoginDataSourceSection> dataSource = self.dataSources[indexPath.section];
if ([dataSource respondsToSelector:@selector(willSelectRow:)]) {
NSUInteger targetRow = [dataSource willSelectRow:indexPath.row];
if (targetRow == NSNotFound) {
targetIndexPath = nil;
} else if (targetRow != indexPath.row) {
targetIndexPath = [NSIndexPath indexPathForRow:targetRow inSection:indexPath.section];
}
} else if (![dataSource respondsToSelector:@selector(didSelectRow:)]) {
targetIndexPath = nil;
}
return targetIndexPath;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
id<VLCNetworkLoginDataSourceSection> dataSource = self.dataSources[indexPath.section];
if ([dataSource respondsToSelector:@selector(didSelectRow:)]) {
[dataSource didSelectRow:indexPath.row];
}
}
@end
/*****************************************************************************
* VLC for iOS
*****************************************************************************
* Copyright (c) 2016 VideoLAN. All rights reserved.
* $Id$
*
* Authors: Vincent L. Cone <vincent.l.cone # tuta.io>
*
* Refer to the COPYING file of the official project for license.
*****************************************************************************/
#import <UIKit/UIKit.h>
#import "VLCNetworkServerLoginInformation.h"
#import "VLCNetworkLoginDataSourceSection.h"
NS_ASSUME_NONNULL_BEGIN
@protocol VLCNetworkLoginDataSourceLoginDelegate;
@interface VLCNetworkLoginDataSourceLogin : NSObject <VLCNetworkLoginDataSourceSection>
@property (nonatomic, weak) id <VLCNetworkLoginDataSourceLoginDelegate> delegate;
@property (nonatomic, nullable) VLCNetworkServerLoginInformation *loginInformation;
@end
@protocol VLCNetworkLoginDataSourceLoginDelegate <NSObject>
- (void)saveLoginDataSource:(VLCNetworkLoginDataSourceLogin *)dataSource;
- (void)connectLoginDataSource:(VLCNetworkLoginDataSourceLogin *)dataSource;
@end
NS_ASSUME_NONNULL_END
/*****************************************************************************
* VLC for iOS
*****************************************************************************
* Copyright (c) 2016 VideoLAN. All rights reserved.
* $Id$
*
* Authors: Vincent L. Cone <vincent.l.cone # tuta.io>
*
* Refer to the COPYING file of the official project for license.
*****************************************************************************/
#import "VLCNetworkLoginDataSourceLogin.h"
#import "VLCNetworkLoginViewFieldCell.h"
#import "VLCNetworkLoginViewButtonCell.h"
typedef NS_ENUM(NSUInteger, VLCNetworkServerLoginIndex) {
VLCNetworkServerLoginIndexServer,
VLCNetworkServerLoginIndexPort,
VLCNetworkServerLoginIndexUsername,
VLCNetworkServerLoginIndexPassword,
VLCNetworkServerLoginIndexConnect,
VLCNetworkServerLoginIndexSave,
VLCNetworkServerLoginIndexCount,
VLCNetworkServerLoginIndexFieldCount = VLCNetworkServerLoginIndexConnect
};
@interface VLCNetworkLoginDataSourceLogin () <VLCNetworkLoginViewFieldCellDelegate>
@property (nonatomic, weak) UITableView *tableView;
@end
@implementation VLCNetworkLoginDataSourceLogin
@synthesize sectionIndex = _sectionIndex;
#pragma mark - API
- (void)registerCellsInTableView:(UITableView *)tableView
{
[tableView registerClass:[VLCNetworkLoginViewButtonCell class] forCellReuseIdentifier:kVLCNetworkLoginViewButtonCellIdentifier];
Class fieldClass = [VLCNetworkLoginViewFieldCell class];
[tableView registerNib:[UINib nibWithNibName:NSStringFromClass(fieldClass) bundle:[NSBundle bundleForClass:fieldClass]]
forCellReuseIdentifier:kVLCNetworkLoginViewFieldCellIdentifier];
}
- (void)setLoginInformation:(VLCNetworkServerLoginInformation *)loginInformation
{
_loginInformation = loginInformation;
[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:self.sectionIndex] withRowAnimation:UITableViewRowAnimationAutomatic];
}
#pragma mark - helper
- (void)configureButtonCell:(VLCNetworkLoginViewButtonCell *)buttonCell forRow:(NSUInteger)row
{
NSString *labelString = nil;
NSUInteger additionalFieldsCount = self.loginInformation.additionalFields.count;
NSUInteger buttonRowIndex = row-additionalFieldsCount;
if (buttonRowIndex == VLCNetworkServerLoginIndexConnect) {
labelString = NSLocalizedString(@"BUTTON_CONNECT", nil);
} else if (buttonRowIndex == VLCNetworkServerLoginIndexSave) {
labelString = NSLocalizedString(@"BUTTON_SAVE", nil);
}
buttonCell.titleString = labelString;
}
- (void)configureFieldCell:(VLCNetworkLoginViewFieldCell *)fieldCell forRow:(NSUInteger)row
{
UIKeyboardType keyboardType = UIKeyboardTypeDefault;
BOOL secureTextEntry = NO;
NSString *labelString = nil;
NSString *valueString = nil;
UIReturnKeyType returnKeyType = UIReturnKeyNext;
switch (row) {
case VLCNetworkServerLoginIndexServer:
keyboardType = UIKeyboardTypeURL;
labelString = NSLocalizedString(@"SERVER", nil);
valueString = self.loginInformation.address;
break;
case VLCNetworkServerLoginIndexPort:
keyboardType = UIKeyboardTypeNumberPad;
labelString = NSLocalizedString(@"SERVER_PORT", nil);
valueString = self.loginInformation.port.stringValue;
break;
case VLCNetworkServerLoginIndexUsername:
labelString = NSLocalizedString(@"USER_LABEL", nil);
valueString = self.loginInformation.username;
break;
case VLCNetworkServerLoginIndexPassword:
labelString = NSLocalizedString(@"PASSWORD_LABEL", nil);