mirror of
https://github.com/netbirdio/gomobile-tvos-fork.git
synced 2026-05-22 18:43:29 -07:00
example/ivy/ios: enable demo functionality
And bring iOS app up to Android capabilities. Fixes golang/go#48694 Change-Id: I0e853cab102e34053ecdb17edb99644aa2f8651a Reviewed-on: https://go-review.googlesource.com/c/mobile/+/357977 Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com> Trust: Hyang-Ah Hana Kim <hyangah@gmail.com> Trust: Peter Weinberger <pjw@google.com>
This commit is contained in:
committed by
Hyang-Ah Hana Kim
parent
7b8bfe0993
commit
170e11ba23
@@ -17,7 +17,7 @@ mkdir work; cd work
|
||||
go mod init work
|
||||
go get -d golang.org/x/mobile/bind@latest
|
||||
go get -d robpike.io/ivy/mobile
|
||||
gomobile bind -target=ios,iossimulator,maccatalyst,macos robpike.io/ivy/mobile
|
||||
gomobile bind -target=ios,iossimulator,maccatalyst,macos robpike.io/ivy/mobile robpike.io/ivy/demo
|
||||
```
|
||||
|
||||
Place the Mobile.xcframework directory in this directory, and
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objectVersion = 52;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
@@ -316,12 +316,16 @@
|
||||
);
|
||||
INFOPLIST_FILE = ivy/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)",
|
||||
);
|
||||
ONLY_ACTIVE_ARCH = NO;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.google.${PRODUCT_NAME:rfc1034identifier}";
|
||||
PRODUCT_NAME = ivy;
|
||||
STRIP_STYLE = debugging;
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
@@ -342,13 +346,16 @@
|
||||
);
|
||||
INFOPLIST_FILE = ivy/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)",
|
||||
);
|
||||
ONLY_ACTIVE_ARCH = NO;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.google.$(PRODUCT_NAME:rfc1034identifier)";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.google.${PRODUCT_NAME:rfc1034identifier}";
|
||||
PRODUCT_NAME = ivy;
|
||||
STRIP_STYLE = debugging;
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="19158" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="mTw-C8-NzX">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="19162" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="mTw-C8-NzX">
|
||||
<device id="retina6_1" orientation="portrait" appearance="light"/>
|
||||
<accessibilityOverrides isEnabled="YES"/>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19141"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19144"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
@@ -55,15 +55,38 @@
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<textField opaque="NO" clipsSubviews="YES" tag="1" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="Type an expression" minimumFontSize="17" clearButtonMode="whileEditing" translatesAutoresizingMaskIntoConstraints="NO" id="9SS-TP-C7c" userLabel="InputField">
|
||||
<rect key="frame" x="20" y="817" width="374" height="34"/>
|
||||
<color key="backgroundColor" red="0.98823529409999999" green="0.98039215690000003" blue="0.81176470590000005" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<rect key="contentStretch" x="1" y="1" width="1" height="1"/>
|
||||
<fontDescription key="fontDescription" name="Menlo-Bold" family="Menlo" pointSize="14"/>
|
||||
<textInputTraits key="textInputTraits" autocorrectionType="no" spellCheckingType="no" keyboardType="alphabet" keyboardAppearance="alert" enablesReturnKeyAutomatically="YES"/>
|
||||
</textField>
|
||||
<stackView opaque="NO" contentMode="scaleToFill" horizontalCompressionResistancePriority="1000" verticalCompressionResistancePriority="1000" alignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="Cn1-rU-W3R">
|
||||
<rect key="frame" x="20" y="831" width="374" height="31"/>
|
||||
<subviews>
|
||||
<textField opaque="NO" clipsSubviews="YES" tag="1" contentMode="scaleToFill" horizontalHuggingPriority="249" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="Type an expression" minimumFontSize="17" clearButtonMode="whileEditing" translatesAutoresizingMaskIntoConstraints="NO" id="9SS-TP-C7c" userLabel="InputField">
|
||||
<rect key="frame" x="0.0" y="0.0" width="301.5" height="31"/>
|
||||
<color key="backgroundColor" red="0.98823529409999999" green="0.98039215690000003" blue="0.81176470590000005" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<rect key="contentStretch" x="1" y="1" width="1" height="1"/>
|
||||
<fontDescription key="fontDescription" name="Menlo-Bold" family="Menlo" pointSize="14"/>
|
||||
<textInputTraits key="textInputTraits" autocorrectionType="no" spellCheckingType="no" keyboardType="alphabet" keyboardAppearance="alert" enablesReturnKeyAutomatically="YES" smartDashesType="no" smartInsertDeleteType="no" smartQuotesType="no"/>
|
||||
</textField>
|
||||
<button opaque="NO" contentMode="scaleToFill" horizontalCompressionResistancePriority="1000" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="eO6-bM-CwW">
|
||||
<rect key="frame" x="301.5" y="0.0" width="72.5" height="31"/>
|
||||
<accessibility key="accessibilityConfiguration" label="OK"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="31" id="1nb-CV-bfg"/>
|
||||
</constraints>
|
||||
<inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
|
||||
<state key="normal" title="Button" image="return" catalog="system"/>
|
||||
<connections>
|
||||
<action selector="okPressed:" destination="BYZ-38-t0r" eventType="touchUpInside" id="258-zN-fwW"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="9SS-TP-C7c" firstAttribute="trailing" secondItem="eO6-bM-CwW" secondAttribute="leading" id="9Fe-Sf-U5p"/>
|
||||
<constraint firstItem="eO6-bM-CwW" firstAttribute="top" secondItem="9SS-TP-C7c" secondAttribute="top" id="9hv-aL-4z2"/>
|
||||
<constraint firstItem="eO6-bM-CwW" firstAttribute="trailing" secondItem="Cn1-rU-W3R" secondAttribute="trailing" id="A4G-YY-4Gn"/>
|
||||
<constraint firstItem="9SS-TP-C7c" firstAttribute="leading" secondItem="Cn1-rU-W3R" secondAttribute="leading" id="i2m-BU-Q4a"/>
|
||||
</constraints>
|
||||
</stackView>
|
||||
<wkWebView opaque="NO" tag="2" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" layoutMarginsFollowReadableWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ga1-Py-9re">
|
||||
<rect key="frame" x="20" y="88" width="374" height="721"/>
|
||||
<rect key="frame" x="20" y="88" width="374" height="737"/>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
<wkWebViewConfiguration key="configuration">
|
||||
<audiovisualMediaTypes key="mediaTypesRequiringUserActionForPlayback" none="YES"/>
|
||||
@@ -73,29 +96,44 @@
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="0.9882352941176471" green="0.98039215686274506" blue="0.81176470588235294" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="ga1-Py-9re" firstAttribute="trailing" secondItem="9SS-TP-C7c" secondAttribute="trailing" id="3b6-rZ-W4R"/>
|
||||
<constraint firstItem="9SS-TP-C7c" firstAttribute="top" secondItem="ga1-Py-9re" secondAttribute="bottom" constant="8" id="B3O-hi-PRD"/>
|
||||
<constraint firstItem="Cn1-rU-W3R" firstAttribute="trailing" secondItem="8bC-Xf-vdC" secondAttribute="trailingMargin" id="7DU-Hc-uk7"/>
|
||||
<constraint firstItem="Cn1-rU-W3R" firstAttribute="bottom" secondItem="wfy-db-euE" secondAttribute="top" id="8mr-vY-R1v"/>
|
||||
<constraint firstItem="ga1-Py-9re" firstAttribute="bottom" secondItem="Cn1-rU-W3R" secondAttribute="top" constant="-6" id="BX0-OH-IJ4"/>
|
||||
<constraint firstItem="ga1-Py-9re" firstAttribute="trailing" secondItem="8bC-Xf-vdC" secondAttribute="trailingMargin" id="Fxh-TE-BtG"/>
|
||||
<constraint firstItem="ga1-Py-9re" firstAttribute="leading" secondItem="9SS-TP-C7c" secondAttribute="leading" id="MhN-JS-MpC"/>
|
||||
<constraint firstItem="wfy-db-euE" firstAttribute="top" secondItem="9SS-TP-C7c" secondAttribute="bottom" constant="11" id="Yvi-br-VHk"/>
|
||||
<constraint firstItem="Cn1-rU-W3R" firstAttribute="leading" secondItem="8bC-Xf-vdC" secondAttribute="leadingMargin" id="LPE-LO-nct"/>
|
||||
<constraint firstItem="ga1-Py-9re" firstAttribute="top" secondItem="8bC-Xf-vdC" secondAttribute="topMargin" id="p9M-sp-ZwC"/>
|
||||
<constraint firstItem="ga1-Py-9re" firstAttribute="leading" secondItem="8bC-Xf-vdC" secondAttribute="leadingMargin" id="pOi-3s-hrr"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<navigationItem key="navigationItem" title="Ivy" id="9fD-A5-WTg">
|
||||
<barButtonItem key="rightBarButtonItem" title="Help" id="aDa-GJ-VpX">
|
||||
<barButtonItem key="leftBarButtonItem" title="Clear" id="70x-xp-aiX">
|
||||
<connections>
|
||||
<segue destination="rfr-rm-AXI" kind="show" id="kuc-xA-dyM"/>
|
||||
<action selector="clear:" destination="BYZ-38-t0r" id="n7k-fg-dil"/>
|
||||
</connections>
|
||||
</barButtonItem>
|
||||
<rightBarButtonItems>
|
||||
<barButtonItem title="Help" id="aDa-GJ-VpX">
|
||||
<connections>
|
||||
<segue destination="rfr-rm-AXI" kind="show" id="kuc-xA-dyM"/>
|
||||
</connections>
|
||||
</barButtonItem>
|
||||
<barButtonItem title="Demo" id="ZN2-PQ-aPW">
|
||||
<connections>
|
||||
<action selector="demo:" destination="BYZ-38-t0r" id="NpG-yh-wMO"/>
|
||||
</connections>
|
||||
</barButtonItem>
|
||||
</rightBarButtonItems>
|
||||
</navigationItem>
|
||||
<connections>
|
||||
<outlet property="bottomConstraint" destination="Yvi-br-VHk" id="EKm-WV-Y1w"/>
|
||||
<outlet property="bottomConstraint" destination="8mr-vY-R1v" id="BqX-Do-vtq"/>
|
||||
<outlet property="input" destination="9SS-TP-C7c" id="jUA-25-4WI"/>
|
||||
<outlet property="okButton" destination="eO6-bM-CwW" id="o9U-hD-NDr"/>
|
||||
<outlet property="tape" destination="ga1-Py-9re" id="00M-9S-MAl"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="990.40178571428567" y="382.60869565217394"/>
|
||||
<point key="canvasLocation" x="989.85507246376824" y="382.36607142857139"/>
|
||||
</scene>
|
||||
<!--Navigation Controller-->
|
||||
<scene sceneID="ZgV-45-Pf8">
|
||||
@@ -130,4 +168,7 @@
|
||||
<point key="canvasLocation" x="271" y="386"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
<resources>
|
||||
<image name="return" catalog="system" width="128" height="101"/>
|
||||
</resources>
|
||||
</document>
|
||||
|
||||
@@ -150,6 +150,13 @@
|
||||
"scale" : "3x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"idiom" : "watch",
|
||||
"role" : "notificationCenter",
|
||||
"scale" : "2x",
|
||||
"size" : "33x33",
|
||||
"subtype" : "45mm"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-80.png",
|
||||
"idiom" : "watch",
|
||||
@@ -166,6 +173,13 @@
|
||||
"size" : "44x44",
|
||||
"subtype" : "40mm"
|
||||
},
|
||||
{
|
||||
"idiom" : "watch",
|
||||
"role" : "appLauncher",
|
||||
"scale" : "2x",
|
||||
"size" : "46x46",
|
||||
"subtype" : "41mm"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-100.png",
|
||||
"idiom" : "watch",
|
||||
@@ -174,6 +188,13 @@
|
||||
"size" : "50x50",
|
||||
"subtype" : "44mm"
|
||||
},
|
||||
{
|
||||
"idiom" : "watch",
|
||||
"role" : "appLauncher",
|
||||
"scale" : "2x",
|
||||
"size" : "51x51",
|
||||
"subtype" : "45mm"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-172.png",
|
||||
"idiom" : "watch",
|
||||
@@ -198,6 +219,13 @@
|
||||
"size" : "108x108",
|
||||
"subtype" : "44mm"
|
||||
},
|
||||
{
|
||||
"idiom" : "watch",
|
||||
"role" : "quickLook",
|
||||
"scale" : "2x",
|
||||
"size" : "117x117",
|
||||
"subtype" : "45mm"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-1024.png",
|
||||
"idiom" : "watch-marketing",
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<string>com.google.$(PRODUCT_NAME:rfc1034identifier)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
|
||||
@@ -14,8 +14,13 @@
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *bottomConstraint;
|
||||
|
||||
// A text input field coupled to an output "tape", rendered with a WKWebView.
|
||||
@property (strong, nonatomic) UITextField *input;
|
||||
@property (weak, nonatomic) IBOutlet UITextField *input;
|
||||
@property (strong, nonatomic) Suggestion *suggestionView;
|
||||
@property (strong, nonatomic) WKWebView *tape;
|
||||
@property (weak, nonatomic) IBOutlet WKWebView *tape;
|
||||
@property (weak, nonatomic) IBOutlet UIButton *okButton;
|
||||
|
||||
- (IBAction)clear:(id)sender;
|
||||
- (IBAction)demo:(id)sender;
|
||||
- (IBAction)okPressed:(id)sender;
|
||||
|
||||
@end
|
||||
|
||||
@@ -9,50 +9,46 @@
|
||||
|
||||
@end
|
||||
|
||||
@implementation IvyController
|
||||
@implementation IvyController {
|
||||
NSArray *demo_lines;
|
||||
int demo_index;
|
||||
}
|
||||
|
||||
- (void)viewDidLoad
|
||||
{
|
||||
[super viewDidLoad];
|
||||
|
||||
self.input = (UITextField *)[self.view viewWithTag:1];
|
||||
|
||||
self.input.delegate = self;
|
||||
self.input.autocorrectionType = UITextAutocorrectionTypeNo;
|
||||
self.input.keyboardType = UIKeyboardTypeNumbersAndPunctuation;
|
||||
|
||||
|
||||
self.suggestionView = [[Suggestion alloc] init];
|
||||
self.suggestionView.delegate = self;
|
||||
|
||||
self.tape = [self.view viewWithTag:2];
|
||||
|
||||
self.tape.UIDelegate = self;
|
||||
|
||||
self->demo_lines=NULL;
|
||||
|
||||
[self.okButton setTitle:@"" forState:UIControlStateNormal];
|
||||
[self.okButton setHidden:TRUE];
|
||||
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
addObserver:self
|
||||
selector:@selector(textDidChange:)
|
||||
name:UITextFieldTextDidChangeNotification
|
||||
object:self.input];
|
||||
addObserver:self
|
||||
selector:@selector(textDidChange:)
|
||||
name:UITextFieldTextDidChangeNotification
|
||||
object:self.input];
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
addObserver:self
|
||||
selector:@selector(keyboardWillShow:)
|
||||
name:UIKeyboardWillShowNotification
|
||||
object:nil];
|
||||
addObserver:self
|
||||
selector:@selector(keyboardWillShow:)
|
||||
name:UIKeyboardWillShowNotification
|
||||
object:nil];
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
addObserver:self
|
||||
selector:@selector(keyboardWillHide:)
|
||||
name:UIKeyboardWillHideNotification
|
||||
object:nil];
|
||||
|
||||
NSURL *bundleURL =
|
||||
[[NSBundle mainBundle] URLForResource:@"tape" withExtension:@"html"];
|
||||
NSURLRequest *request = [NSURLRequest requestWithURL:bundleURL];
|
||||
[self.tape loadRequest:request];
|
||||
self.tape.UIDelegate = self;
|
||||
addObserver:self
|
||||
selector:@selector(keyboardWillHide:)
|
||||
name:UIKeyboardWillHideNotification
|
||||
object:nil];
|
||||
|
||||
[self.input becomeFirstResponder];
|
||||
}
|
||||
|
||||
- (void)viewDidAppear:(BOOL)animated
|
||||
{
|
||||
[self.view endEditing:YES];
|
||||
[self clear:NULL];
|
||||
}
|
||||
|
||||
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
|
||||
@@ -75,33 +71,14 @@
|
||||
}
|
||||
|
||||
- (BOOL)textField:(UITextField *)textField
|
||||
shouldChangeCharactersInRange:(NSRange)range
|
||||
replacementString:(NSString *)str
|
||||
shouldChangeCharactersInRange:(NSRange)range
|
||||
replacementString:(NSString *)str
|
||||
{
|
||||
if ([str isEqualToString:@"\n"]) {
|
||||
[self
|
||||
appendTape:[NSString stringWithFormat:@"<b>%@</b>", [self.input text]]];
|
||||
NSString *expr = [self.input.text stringByAppendingString:@"\n"];
|
||||
NSError *err;
|
||||
NSString *result = MobileEval(expr, &err);
|
||||
if (err != nil) {
|
||||
result = err.description;
|
||||
}
|
||||
result = [result
|
||||
stringByTrimmingCharactersInSet:[NSCharacterSet newlineCharacterSet]];
|
||||
result =
|
||||
[result stringByReplacingOccurrencesOfString:@"<" withString:@"<"];
|
||||
result =
|
||||
[result stringByReplacingOccurrencesOfString:@">" withString:@">"];
|
||||
NSMutableArray *lines =
|
||||
(NSMutableArray *)[result componentsSeparatedByString:@"\n"];
|
||||
for (NSMutableString *line in lines) {
|
||||
[self appendTape:line];
|
||||
}
|
||||
self.input.text = @"";
|
||||
[self enterPressed];
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
@@ -121,51 +98,98 @@
|
||||
// Move the input text field up, as the keyboard has taken some of the screen.
|
||||
NSDictionary *info = [aNotification userInfo];
|
||||
CGRect kbFrame =
|
||||
[[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
|
||||
[[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
|
||||
NSNumber *duration =
|
||||
[info objectForKey:UIKeyboardAnimationDurationUserInfoKey];
|
||||
|
||||
[info objectForKey:UIKeyboardAnimationDurationUserInfoKey];
|
||||
|
||||
UIViewAnimationCurve keyboardTransitionAnimationCurve;
|
||||
[[info valueForKey:UIKeyboardAnimationCurveUserInfoKey]
|
||||
getValue:&keyboardTransitionAnimationCurve];
|
||||
getValue:&keyboardTransitionAnimationCurve];
|
||||
UIViewAnimationOptions options =
|
||||
keyboardTransitionAnimationCurve | keyboardTransitionAnimationCurve << 16;
|
||||
|
||||
keyboardTransitionAnimationCurve | keyboardTransitionAnimationCurve << 16;
|
||||
|
||||
[UIView animateWithDuration:duration.floatValue
|
||||
delay:0
|
||||
options:options
|
||||
animations:^{
|
||||
self.bottomConstraint.constant = kbFrame.size.height;
|
||||
delay:0
|
||||
options:options
|
||||
animations:^{
|
||||
self.bottomConstraint.constant = 0 - kbFrame.size.height;
|
||||
[self.view layoutIfNeeded];
|
||||
}
|
||||
completion:^(BOOL finished) {
|
||||
}
|
||||
completion:^(BOOL finished) {
|
||||
[self scrollTapeToBottom];
|
||||
}];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)keyboardWillHide:(NSNotification *)aNotification
|
||||
{
|
||||
// Move the input text field back down.
|
||||
NSDictionary *info = [aNotification userInfo];
|
||||
|
||||
NSNumber *duration =
|
||||
[info objectForKey:UIKeyboardAnimationDurationUserInfoKey];
|
||||
[info objectForKey:UIKeyboardAnimationDurationUserInfoKey];
|
||||
|
||||
UIViewAnimationCurve keyboardTransitionAnimationCurve;
|
||||
[[info valueForKey:UIKeyboardAnimationCurveUserInfoKey]
|
||||
getValue:&keyboardTransitionAnimationCurve];
|
||||
getValue:&keyboardTransitionAnimationCurve];
|
||||
UIViewAnimationOptions options =
|
||||
keyboardTransitionAnimationCurve | keyboardTransitionAnimationCurve << 16;
|
||||
|
||||
keyboardTransitionAnimationCurve | keyboardTransitionAnimationCurve << 16;
|
||||
|
||||
int offset = self.input.inputAccessoryView != NULL ? self.suggestionView.frame.size.height : 0;
|
||||
|
||||
[UIView animateWithDuration:duration.floatValue
|
||||
delay:0
|
||||
options:options
|
||||
animations:^{
|
||||
self.bottomConstraint.constant = 32;
|
||||
delay:0
|
||||
options:options
|
||||
animations:^{
|
||||
self.bottomConstraint.constant = 0 - offset;
|
||||
[self.view layoutIfNeeded];
|
||||
}
|
||||
completion:^(BOOL finished) {
|
||||
}
|
||||
completion:^(BOOL finished) {
|
||||
[self scrollTapeToBottom];
|
||||
}];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)enterPressed
|
||||
{
|
||||
NSString *text = self.input.text;
|
||||
if ([text isEqual:@""]){
|
||||
if(self->demo_lines==NULL){
|
||||
return;
|
||||
}
|
||||
while (demo_index < self->demo_lines.count) {
|
||||
NSString *line = self->demo_lines[self->demo_index++];
|
||||
if([line hasPrefix:@"#"]) {
|
||||
[self appendTape:line tag:@"comment"];
|
||||
} else {
|
||||
self.input.text = line;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (self->demo_lines!=NULL && [text isEqual:@"quit"]) {
|
||||
[self unloadDemo];
|
||||
} else {
|
||||
[self appendTape:text tag:@"expr"];
|
||||
NSString *expr = [text stringByAppendingString:@"\n"];
|
||||
NSError *err;
|
||||
NSString *result = MobileEval(expr, &err);
|
||||
if (err != nil) {
|
||||
result = err.description;
|
||||
}
|
||||
result = [result
|
||||
stringByTrimmingCharactersInSet:[NSCharacterSet newlineCharacterSet]];
|
||||
result =
|
||||
[result stringByReplacingOccurrencesOfString:@"<" withString:@"<"];
|
||||
result =
|
||||
[result stringByReplacingOccurrencesOfString:@">" withString:@">"];
|
||||
NSMutableArray *lines =
|
||||
(NSMutableArray *)[result componentsSeparatedByString:@"\n"];
|
||||
for (NSMutableString *line in lines) {
|
||||
if ([line hasPrefix:@"#"])
|
||||
[self appendTape:line tag:@"comment"];
|
||||
else
|
||||
[self appendTape:line tag:@"result"];
|
||||
}
|
||||
self.input.text = @"";
|
||||
}
|
||||
}
|
||||
|
||||
- (void)scrollTapeToBottom
|
||||
@@ -174,11 +198,46 @@
|
||||
[self.tape evaluateJavaScript:scroll completionHandler:nil];
|
||||
}
|
||||
|
||||
- (void)appendTape:(NSString *)text
|
||||
- (void)appendTape:(NSString *)text tag:(NSString *)tag
|
||||
{
|
||||
NSString *injectSrc = @"appendDiv('%@');";
|
||||
NSString *runToInject = [NSString stringWithFormat:injectSrc, text];
|
||||
NSString *injectSrc = @"appendDiv('%@','%@');";
|
||||
NSString *runToInject = [NSString stringWithFormat:injectSrc, text, tag];
|
||||
[self.tape evaluateJavaScript:runToInject completionHandler:nil];
|
||||
[self scrollTapeToBottom];
|
||||
}
|
||||
|
||||
- (void)loadDemo
|
||||
{
|
||||
[self.okButton setHidden:FALSE];
|
||||
NSString *text = DemoText();
|
||||
|
||||
self->demo_lines = [text componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];
|
||||
self->demo_index = 0;
|
||||
self.input.text = @"";
|
||||
[self enterPressed];
|
||||
}
|
||||
- (void)unloadDemo
|
||||
{
|
||||
[self.okButton setHidden:TRUE];
|
||||
self->demo_lines=NULL;
|
||||
self.input.text = @"";
|
||||
}
|
||||
- (IBAction)okPressed:(id)sender {
|
||||
[self enterPressed];
|
||||
}
|
||||
|
||||
- (IBAction)demo:(id)sender {
|
||||
if (self->demo_lines) { // demo already running
|
||||
[self enterPressed];
|
||||
} else {
|
||||
[self loadDemo];
|
||||
}
|
||||
}
|
||||
|
||||
- (IBAction)clear:(id)sender {
|
||||
[self unloadDemo];
|
||||
NSString *string = [NSString stringWithContentsOfFile:[[NSBundle mainBundle]
|
||||
pathForResource:@"tape" ofType:@"html"] encoding:NSUTF8StringEncoding error:NULL];
|
||||
[self.tape loadHTMLString:string baseURL:NULL];
|
||||
}
|
||||
@end
|
||||
|
||||
@@ -5,40 +5,56 @@ license that can be found in the LICENSE file.
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<meta name='viewport' content='width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no'>
|
||||
<style>
|
||||
body {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
margin-top: 20px;
|
||||
font-family: Menlo, monospace;
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no" charset="UTF-8">
|
||||
<style>
|
||||
body {
|
||||
font-family: sans-serif;
|
||||
}
|
||||
div {
|
||||
padding: 1;
|
||||
white-space: pre-wrap;
|
||||
font-family: "Roboto Mono", monospace;
|
||||
}
|
||||
.comment {
|
||||
color: grey;
|
||||
}
|
||||
.expr {
|
||||
font-weight: bold;
|
||||
}
|
||||
.flow-hide {
|
||||
text-overflow: ellipsis;
|
||||
word-break: break-all;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
.flow-show {
|
||||
word-break: break-all;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
|
||||
function flowClick(el) {
|
||||
el.classList.toggle("flow-hide");
|
||||
el.classList.toggle("flow-show");
|
||||
}
|
||||
|
||||
.flowhide {
|
||||
text-overflow: ellipsis;
|
||||
word-break: break-word;
|
||||
overflow-wrap: break-word;
|
||||
function appendDiv(txt, tag) {
|
||||
var el = document.createElement("div");
|
||||
el.innerHTML = txt;
|
||||
if (tag == "comment") {
|
||||
el.classList.add("comment");
|
||||
} else if (tag == "expr") {
|
||||
el.classList.add("expr");
|
||||
} else {
|
||||
el.classList.add("flow-show");
|
||||
el.onclick = function() {
|
||||
flowClick(el);
|
||||
};
|
||||
}
|
||||
document.body.appendChild(el);
|
||||
}
|
||||
|
||||
.flowshow {
|
||||
word-break: break-all;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
function flowclick(el) {
|
||||
el.classList.toggle("flowhide");
|
||||
el.classList.toggle("flowshow");
|
||||
}
|
||||
function appendDiv(text) {
|
||||
var el = document.createElement("div");
|
||||
el.classList.add("flowhide");
|
||||
el.innerHTML = text;
|
||||
el.onclick = function() {
|
||||
flowclick(el);
|
||||
};
|
||||
document.body.appendChild(el);
|
||||
window.scrollBy(0, document.body.offsetHeight);
|
||||
}
|
||||
</script>
|
||||
<body>
|
||||
</body>
|
||||
|
||||
Reference in New Issue
Block a user