├── .gitignore
├── DefaultIcon-ios.png
├── DefaultIcon.png
├── LICENSE
├── README.md
├── app
├── alloy.jmk
├── alloy.js
├── assets
│ ├── android
│ │ ├── appicon.png
│ │ └── images
│ │ │ ├── launcher.png
│ │ │ └── logo.png
│ └── iphone
│ │ ├── LaunchLogo@2x~ipad.png
│ │ ├── LaunchLogo@2x~iphone.png
│ │ ├── LaunchLogo@3x~iphone.png
│ │ ├── LaunchLogo~ipad.png
│ │ ├── LaunchLogo~iphone.png
│ │ └── images
│ │ ├── tabIcon.png
│ │ ├── tabIcon@2x.png
│ │ └── tabIcon@3x.png
├── config.json
├── controllers
│ ├── android
│ │ ├── keyboard.js
│ │ ├── launcher.js
│ │ ├── streetview.js
│ │ ├── tableview.js
│ │ ├── transitions.js
│ │ ├── transitions_a.js
│ │ └── transitions_b.js
│ ├── console.js
│ ├── index.js
│ ├── ios
│ │ ├── appshortcuts.js
│ │ ├── keyboard.js
│ │ ├── listview.js
│ │ ├── livephoto.js
│ │ ├── menupopup.js
│ │ ├── popover.js
│ │ ├── scrollview.js
│ │ ├── touch.js
│ │ └── watchos.js
│ └── tab.js
├── lib
│ └── log.js
├── platform
│ ├── android
│ │ └── res
│ │ │ ├── drawable-hdpi
│ │ │ ├── appicon.png
│ │ │ └── background.9.png
│ │ │ ├── drawable-mdpi
│ │ │ ├── appicon.png
│ │ │ └── background.9.png
│ │ │ ├── drawable-xhdpi
│ │ │ ├── appicon.png
│ │ │ └── background.9.png
│ │ │ ├── drawable-xxhdpi
│ │ │ ├── appicon.png
│ │ │ └── background.9.png
│ │ │ └── values
│ │ │ └── custom_theme.xml
│ └── ios
│ │ └── _LaunchScreen.storyboard
├── styles
│ ├── android
│ │ ├── keyboard.tss
│ │ ├── streetview.tss
│ │ ├── transitions_a.tss
│ │ └── transitions_b.tss
│ ├── app.tss
│ ├── console.tss
│ ├── index.tss
│ ├── ios
│ │ ├── listview.tss
│ │ ├── livephoto.tss
│ │ ├── progressbar.tss
│ │ ├── touch.tss
│ │ └── window.tss
│ └── tab.tss
└── views
│ ├── android
│ ├── keyboard.xml
│ ├── launcher.xml
│ ├── streetview.xml
│ ├── tableview.xml
│ ├── transitions.xml
│ ├── transitions_a.xml
│ └── transitions_b.xml
│ ├── console.xml
│ ├── index.xml
│ ├── ios
│ ├── appshortcuts.xml
│ ├── keyboard.xml
│ ├── listview.xml
│ ├── livephoto.xml
│ ├── menupopup.xml
│ ├── popover.xml
│ ├── progressbar.xml
│ ├── scrollview.xml
│ ├── touch.xml
│ ├── watchos.xml
│ └── window.xml
│ └── tab.xml
├── docs
├── android.md
├── assets
│ ├── avd.png
│ ├── image.png
│ ├── insertion.png
│ ├── ipadpro.png
│ ├── launch-builtin.png
│ ├── launch-custom.png
│ ├── menupopup.png
│ ├── module.png
│ ├── screenshots.png
│ ├── simpholders.png
│ ├── splitview.png
│ ├── streetview.png
│ ├── tab.png
│ └── transitions.png
├── ios.md
├── launchfiles.md
├── livephotos.md
├── streetview.md
└── transitions.md
├── extensions
└── Ti 5.2.0
│ ├── Ti 5.2.0 WatchKit App
│ ├── Assets.xcassets
│ │ └── AppIcon.appiconset
│ │ │ ├── Contents.json
│ │ │ ├── icon-24@2x.png
│ │ │ ├── icon-27.5@2x.png
│ │ │ ├── icon-29@2x.png
│ │ │ ├── icon-29@3x.png
│ │ │ ├── icon-40@2x.png
│ │ │ ├── icon-44@2x.png
│ │ │ ├── icon-86@2x.png
│ │ │ └── icon-98@2x.png
│ ├── Base.lproj
│ │ └── Interface.storyboard
│ └── Info.plist
│ ├── Ti 5.2.0 WatchKit Extension
│ ├── Assets.xcassets
│ │ └── README__ignoredByTemplate__
│ ├── ExtensionDelegate.h
│ ├── ExtensionDelegate.m
│ ├── Info.plist
│ ├── InterfaceController.h
│ ├── InterfaceController.m
│ ├── NotificationController.h
│ ├── NotificationController.m
│ └── PushNotificationPayload.apns
│ └── Ti 5.2.0.xcodeproj
│ └── project.pbxproj
├── platform
└── ios
│ └── _LaunchScreen.storyboard
├── plugins
├── ti.alloy
│ ├── hooks
│ │ ├── alloy.js
│ │ └── deepclean.js
│ └── plugin.py
└── ti.version
│ └── 1.0
│ └── hooks
│ └── version.js
└── tiapp.xml
/.gitignore:
--------------------------------------------------------------------------------
1 | _assets
2 | .DS_Store
3 | Resources
4 | build.log
5 | build
6 | npm-debug.log
7 | tmp
8 | .map
9 | .project
10 | .settings
11 | Thumbs.db
12 | extensions/Ti 5.2.0/Ti 5.2.0.xcodeproj/xcuserdata
13 | extensions/Ti 5.2.0/Ti 5.2.0.xcodeproj/project.xcworkspace
14 | NOTES.md
15 | /platform
16 | /i18n
17 |
--------------------------------------------------------------------------------
/DefaultIcon-ios.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appcelerator-developer-relations/appc-sample-ti520/e91e8b14182114b2912d60cd4604dc06170df8e7/DefaultIcon-ios.png
--------------------------------------------------------------------------------
/DefaultIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appcelerator-developer-relations/appc-sample-ti520/e91e8b14182114b2912d60cd4604dc06170df8e7/DefaultIcon.png
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright 2016 Appcelerator, Inc.
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | (or the full text of the license is below)
10 |
11 | Unless required by applicable law or agreed to in writing, software
12 | distributed under the License is distributed on an "AS IS" BASIS,
13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | See the License for the specific language governing permissions and
15 | limitations under the License.
16 |
17 |
18 |
19 | Apache License
20 | Version 2.0, January 2004
21 | http://www.apache.org/licenses/
22 |
23 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
24 |
25 | 1. Definitions.
26 |
27 | "License" shall mean the terms and conditions for use, reproduction,
28 | and distribution as defined by Sections 1 through 9 of this document.
29 |
30 | "Licensor" shall mean the copyright owner or entity authorized by
31 | the copyright owner that is granting the License.
32 |
33 | "Legal Entity" shall mean the union of the acting entity and all
34 | other entities that control, are controlled by, or are under common
35 | control with that entity. For the purposes of this definition,
36 | "control" means (i) the power, direct or indirect, to cause the
37 | direction or management of such entity, whether by contract or
38 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
39 | outstanding shares, or (iii) beneficial ownership of such entity.
40 |
41 | "You" (or "Your") shall mean an individual or Legal Entity
42 | exercising permissions granted by this License.
43 |
44 | "Source" form shall mean the preferred form for making modifications,
45 | including but not limited to software source code, documentation
46 | source, and configuration files.
47 |
48 | "Object" form shall mean any form resulting from mechanical
49 | transformation or translation of a Source form, including but
50 | not limited to compiled object code, generated documentation,
51 | and conversions to other media types.
52 |
53 | "Work" shall mean the work of authorship, whether in Source or
54 | Object form, made available under the License, as indicated by a
55 | copyright notice that is included in or attached to the work
56 | (an example is provided in the Appendix below).
57 |
58 | "Derivative Works" shall mean any work, whether in Source or Object
59 | form, that is based on (or derived from) the Work and for which the
60 | editorial revisions, annotations, elaborations, or other modifications
61 | represent, as a whole, an original work of authorship. For the purposes
62 | of this License, Derivative Works shall not include works that remain
63 | separable from, or merely link (or bind by name) to the interfaces of,
64 | the Work and Derivative Works thereof.
65 |
66 | "Contribution" shall mean any work of authorship, including
67 | the original version of the Work and any modifications or additions
68 | to that Work or Derivative Works thereof, that is intentionally
69 | submitted to Licensor for inclusion in the Work by the copyright owner
70 | or by an individual or Legal Entity authorized to submit on behalf of
71 | the copyright owner. For the purposes of this definition, "submitted"
72 | means any form of electronic, verbal, or written communication sent
73 | to the Licensor or its representatives, including but not limited to
74 | communication on electronic mailing lists, source code control systems,
75 | and issue tracking systems that are managed by, or on behalf of, the
76 | Licensor for the purpose of discussing and improving the Work, but
77 | excluding communication that is conspicuously marked or otherwise
78 | designated in writing by the copyright owner as "Not a Contribution."
79 |
80 | "Contributor" shall mean Licensor and any individual or Legal Entity
81 | on behalf of whom a Contribution has been received by Licensor and
82 | subsequently incorporated within the Work.
83 |
84 | 2. Grant of Copyright License. Subject to the terms and conditions of
85 | this License, each Contributor hereby grants to You a perpetual,
86 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
87 | copyright license to reproduce, prepare Derivative Works of,
88 | publicly display, publicly perform, sublicense, and distribute the
89 | Work and such Derivative Works in Source or Object form.
90 |
91 | 3. Grant of Patent License. Subject to the terms and conditions of
92 | this License, each Contributor hereby grants to You a perpetual,
93 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
94 | (except as stated in this section) patent license to make, have made,
95 | use, offer to sell, sell, import, and otherwise transfer the Work,
96 | where such license applies only to those patent claims licensable
97 | by such Contributor that are necessarily infringed by their
98 | Contribution(s) alone or by combination of their Contribution(s)
99 | with the Work to which such Contribution(s) was submitted. If You
100 | institute patent litigation against any entity (including a
101 | cross-claim or counterclaim in a lawsuit) alleging that the Work
102 | or a Contribution incorporated within the Work constitutes direct
103 | or contributory patent infringement, then any patent licenses
104 | granted to You under this License for that Work shall terminate
105 | as of the date such litigation is filed.
106 |
107 | 4. Redistribution. You may reproduce and distribute copies of the
108 | Work or Derivative Works thereof in any medium, with or without
109 | modifications, and in Source or Object form, provided that You
110 | meet the following conditions:
111 |
112 | (a) You must give any other recipients of the Work or
113 | Derivative Works a copy of this License; and
114 |
115 | (b) You must cause any modified files to carry prominent notices
116 | stating that You changed the files; and
117 |
118 | (c) You must retain, in the Source form of any Derivative Works
119 | that You distribute, all copyright, patent, trademark, and
120 | attribution notices from the Source form of the Work,
121 | excluding those notices that do not pertain to any part of
122 | the Derivative Works; and
123 |
124 | (d) If the Work includes a "NOTICE" text file as part of its
125 | distribution, then any Derivative Works that You distribute must
126 | include a readable copy of the attribution notices contained
127 | within such NOTICE file, excluding those notices that do not
128 | pertain to any part of the Derivative Works, in at least one
129 | of the following places: within a NOTICE text file distributed
130 | as part of the Derivative Works; within the Source form or
131 | documentation, if provided along with the Derivative Works; or,
132 | within a display generated by the Derivative Works, if and
133 | wherever such third-party notices normally appear. The contents
134 | of the NOTICE file are for informational purposes only and
135 | do not modify the License. You may add Your own attribution
136 | notices within Derivative Works that You distribute, alongside
137 | or as an addendum to the NOTICE text from the Work, provided
138 | that such additional attribution notices cannot be construed
139 | as modifying the License.
140 |
141 | You may add Your own copyright statement to Your modifications and
142 | may provide additional or different license terms and conditions
143 | for use, reproduction, or distribution of Your modifications, or
144 | for any such Derivative Works as a whole, provided Your use,
145 | reproduction, and distribution of the Work otherwise complies with
146 | the conditions stated in this License.
147 |
148 | 5. Submission of Contributions. Unless You explicitly state otherwise,
149 | any Contribution intentionally submitted for inclusion in the Work
150 | by You to the Licensor shall be under the terms and conditions of
151 | this License, without any additional terms or conditions.
152 | Notwithstanding the above, nothing herein shall supersede or modify
153 | the terms of any separate license agreement you may have executed
154 | with Licensor regarding such Contributions.
155 |
156 | 6. Trademarks. This License does not grant permission to use the trade
157 | names, trademarks, service marks, or product names of the Licensor,
158 | except as required for reasonable and customary use in describing the
159 | origin of the Work and reproducing the content of the NOTICE file.
160 |
161 | 7. Disclaimer of Warranty. Unless required by applicable law or
162 | agreed to in writing, Licensor provides the Work (and each
163 | Contributor provides its Contributions) on an "AS IS" BASIS,
164 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
165 | implied, including, without limitation, any warranties or conditions
166 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
167 | PARTICULAR PURPOSE. You are solely responsible for determining the
168 | appropriateness of using or redistributing the Work and assume any
169 | risks associated with Your exercise of permissions under this License.
170 |
171 | 8. Limitation of Liability. In no event and under no legal theory,
172 | whether in tort (including negligence), contract, or otherwise,
173 | unless required by applicable law (such as deliberate and grossly
174 | negligent acts) or agreed to in writing, shall any Contributor be
175 | liable to You for damages, including any direct, indirect, special,
176 | incidental, or consequential damages of any character arising as a
177 | result of this License or out of the use or inability to use the
178 | Work (including but not limited to damages for loss of goodwill,
179 | work stoppage, computer failure or malfunction, or any and all
180 | other commercial damages or losses), even if such Contributor
181 | has been advised of the possibility of such damages.
182 |
183 | 9. Accepting Warranty or Additional Liability. While redistributing
184 | the Work or Derivative Works thereof, You may choose to offer,
185 | and charge a fee for, acceptance of support, warranty, indemnity,
186 | or other liability obligations and/or rights consistent with this
187 | License. However, in accepting such obligations, You may act only
188 | on Your own behalf and on Your sole responsibility, not on behalf
189 | of any other Contributor, and only if You agree to indemnify,
190 | defend, and hold each Contributor harmless for any liability
191 | incurred by, or claims asserted against, such Contributor by reason
192 | of your accepting any such warranty or additional liability.
193 |
194 | END OF TERMS AND CONDITIONS
195 |
196 | APPENDIX: How to apply the Apache License to your work.
197 |
198 | To apply the Apache License to your work, attach the following
199 | boilerplate notice, with the fields enclosed by brackets "[]"
200 | replaced with your own identifying information. (Don't include
201 | the brackets!) The text should be enclosed in the appropriate
202 | comment syntax for the file format. We also recommend that a
203 | file or class name and description of purpose be included on the
204 | same "printed page" as the copyright notice for easier
205 | identification within third-party archives.
206 |
207 | Copyright [yyyy] [name of copyright owner]
208 |
209 | Licensed under the Apache License, Version 2.0 (the "License");
210 | you may not use this file except in compliance with the License.
211 | You may obtain a copy of the License at
212 |
213 | http://www.apache.org/licenses/LICENSE-2.0
214 |
215 | Unless required by applicable law or agreed to in writing, software
216 | distributed under the License is distributed on an "AS IS" BASIS,
217 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
218 | See the License for the specific language governing permissions and
219 | limitations under the License.
220 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Titanium 5.2.0 Sample App
2 |
3 | > **NOTE:** This Sample App requires Titanium >=5.2.2<5.3 and Alloy >=1.8.5 (part of AppC CLI >=5.2.2). It supports Android 4.x and iOS 9.x. Some examples might be restricted to specific platforms or devices.
4 |
5 | 
6 |
7 | For more information on Titanium 5.2.0 see the [official announcement](http://www.appcelerator.com/blog/2016/02/ga-release-of-cli-5-2-titanium-5-2-and-studio-4-5/), which also links the release notes and full list of closed tickets.
8 |
9 | ## Walkthroughs
10 |
11 | The examples and code itself should be fairly self explanatory, but we've published detailed walkthroughs on some of the main features:
12 |
13 | * [Launch Files, iPad Pro, Slide Over and Split View](docs/launchfiles.md)
14 | * [Live Photos](docs/livephotos.md)
15 | * [Google Street View Panorama](docs/streetview.md)
16 | * [Android Activity & Shared Element Transitions](docs/transitions.md)
17 | * [Wrap-up for iOS](docs/ios.md)
18 | * [Wrap-up for Android](docs/android.md)
19 |
20 | ## Running the Sample
21 |
22 | ### Via Appcelerator Studio
23 |
24 | 1. Import it via *Dashboard* if available.
25 | 2. Or import it via *File > Import... > Git > Git Repository as New Project* with *URI*:
26 |
27 | https://github.com/appcelerator-developer-relations/appc-sample-ti520
28 |
29 | 3. Select a Simulator or Device to build to via *Run > Run As*.
30 |
31 | ### Via CLI
32 |
33 | 1. Clone the repository:
34 |
35 | git clone https://github.com/appcelerator-developer-relations/appc-sample-ti520
36 |
37 | 2. To run it with `appc run` first import it to the platform:
38 |
39 | appc new --import --no-services
40 |
41 | 3. Build to Simulator or Device:
42 |
43 | [appc run | ti build] -p ios [-T device]
44 |
--------------------------------------------------------------------------------
/app/alloy.jmk:
--------------------------------------------------------------------------------
1 | task('pre:load', function(event, logger) {
2 |
3 | if (event.minVersion) {
4 | var pkg = require(require('path').join(process.mainModule.filename, '..', '..', 'package.json'));
5 |
6 | if (versionStringToInt(pkg.version) < versionStringToInt(event.minVersion)) {
7 | logger.error('This app requires Alloy ' + event.minVersion + ' or later instead of ' + pkg.version);
8 | process.exit(1);
9 | }
10 | }
11 | });
12 |
13 | function versionStringToInt(versionStr) {
14 | return versionStr.split(/[^0-9]+/).reverse().reduce(function(previousValue, currentValue, currentIndex) {
15 | return previousValue + Math.pow(100, currentIndex) * parseInt(currentValue, 10);
16 | }, 0);
17 | }
18 |
--------------------------------------------------------------------------------
/app/alloy.js:
--------------------------------------------------------------------------------
1 | /* global Alloy, ENV_PROD */
2 |
3 | var log = require('log');
4 |
5 | // The contents of this file will be executed before any of
6 | // your view controllers are ever executed, including the index.
7 | // You have access to all functionality on the `Alloy` namespace.
8 | //
9 | // This is a great place to do any initialization for your app
10 | // or create any global variables/functions that you'd like to
11 | // make available throughout your app. You can easily make things
12 | // accessible globally by attaching them to the `Alloy.Globals`
13 | // object. For example:
14 | //
15 | // Alloy.Globals.someGlobalFunction = function(){};
16 |
17 | /**
18 | * It's a best practice to your code in alloy.js in a self-executing function
19 | * since any variable declared here will be in global scope and never garbage
20 | * collected. Use this or global to explicitly define a global, but rather
21 | * use Alloy.Globals or a CommonJS module you require where needed.
22 | */
23 | (function(global) {
24 |
25 | // This variable would have been global without the above SEF
26 | var versions = Ti.version.split('.');
27 |
28 | // Used in the index view and controller to check if the appw as build with Ti 5.2 or later
29 | Alloy.Globals.isSupported = (parseInt(versions[0], 10) >= 5 && parseInt(versions[1], 10) >= 2);
30 |
31 | // Used in index.tss to set flags for supported examples
32 | Alloy.Globals.isForceTouchSupported = (OS_IOS && Ti.UI.iOS.forceTouchSupported);
33 | Alloy.Globals.isWatchSupported = (OS_IOS && Ti.WatchSession.isSupported);
34 |
35 | if (OS_IOS) {
36 | initAppshortcuts();
37 | }
38 |
39 | })(this);
40 |
41 | // Set in controllers/appshortcuts.js
42 | function initAppshortcuts() {
43 |
44 | // Fired when the shortcut is used
45 | Ti.App.iOS.addEventListener('shortcutitemclick', function onShortcutitemclick(e) {
46 | log.args('Ti.App.iOS:shortcutitemclick', e);
47 |
48 | alert('Hi ' + e.userInfo.person.fullName);
49 | });
50 | }
51 |
--------------------------------------------------------------------------------
/app/assets/android/appicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appcelerator-developer-relations/appc-sample-ti520/e91e8b14182114b2912d60cd4604dc06170df8e7/app/assets/android/appicon.png
--------------------------------------------------------------------------------
/app/assets/android/images/launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appcelerator-developer-relations/appc-sample-ti520/e91e8b14182114b2912d60cd4604dc06170df8e7/app/assets/android/images/launcher.png
--------------------------------------------------------------------------------
/app/assets/android/images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appcelerator-developer-relations/appc-sample-ti520/e91e8b14182114b2912d60cd4604dc06170df8e7/app/assets/android/images/logo.png
--------------------------------------------------------------------------------
/app/assets/iphone/LaunchLogo@2x~ipad.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appcelerator-developer-relations/appc-sample-ti520/e91e8b14182114b2912d60cd4604dc06170df8e7/app/assets/iphone/LaunchLogo@2x~ipad.png
--------------------------------------------------------------------------------
/app/assets/iphone/LaunchLogo@2x~iphone.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appcelerator-developer-relations/appc-sample-ti520/e91e8b14182114b2912d60cd4604dc06170df8e7/app/assets/iphone/LaunchLogo@2x~iphone.png
--------------------------------------------------------------------------------
/app/assets/iphone/LaunchLogo@3x~iphone.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appcelerator-developer-relations/appc-sample-ti520/e91e8b14182114b2912d60cd4604dc06170df8e7/app/assets/iphone/LaunchLogo@3x~iphone.png
--------------------------------------------------------------------------------
/app/assets/iphone/LaunchLogo~ipad.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appcelerator-developer-relations/appc-sample-ti520/e91e8b14182114b2912d60cd4604dc06170df8e7/app/assets/iphone/LaunchLogo~ipad.png
--------------------------------------------------------------------------------
/app/assets/iphone/LaunchLogo~iphone.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appcelerator-developer-relations/appc-sample-ti520/e91e8b14182114b2912d60cd4604dc06170df8e7/app/assets/iphone/LaunchLogo~iphone.png
--------------------------------------------------------------------------------
/app/assets/iphone/images/tabIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appcelerator-developer-relations/appc-sample-ti520/e91e8b14182114b2912d60cd4604dc06170df8e7/app/assets/iphone/images/tabIcon.png
--------------------------------------------------------------------------------
/app/assets/iphone/images/tabIcon@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appcelerator-developer-relations/appc-sample-ti520/e91e8b14182114b2912d60cd4604dc06170df8e7/app/assets/iphone/images/tabIcon@2x.png
--------------------------------------------------------------------------------
/app/assets/iphone/images/tabIcon@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appcelerator-developer-relations/appc-sample-ti520/e91e8b14182114b2912d60cd4604dc06170df8e7/app/assets/iphone/images/tabIcon@3x.png
--------------------------------------------------------------------------------
/app/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "global": {
3 | "brandPrimary": "#CD1625",
4 | "brandSecondary": "#484950",
5 | "brandSuccess": "#5cb85c",
6 | "minVersion": "1.8.5"
7 | },
8 | "env:development": {},
9 | "env:test": {},
10 | "env:production": {},
11 | "os:android": {},
12 | "os:blackberry": {},
13 | "os:ios": {},
14 | "os:mobileweb": {},
15 | "os:windows": {},
16 | "dependencies": {}
17 | }
18 |
--------------------------------------------------------------------------------
/app/controllers/android/keyboard.js:
--------------------------------------------------------------------------------
1 | var log = require('log');
2 |
3 | function closeWindow() {
4 | $.win.close();
5 | }
6 |
7 | function setInputType() {
8 | var names = [];
9 | var inputType = [];
10 |
11 | if ($.number.value) {
12 | names.push('Ti.UI.INPUT_TYPE_CLASS_NUMBER');
13 | inputType.push(Ti.UI.INPUT_TYPE_CLASS_NUMBER);
14 | }
15 |
16 | if ($.text.value) {
17 | names.push('Ti.UI.INPUT_TYPE_CLASS_TEXT');
18 | inputType.push(Ti.UI.INPUT_TYPE_CLASS_TEXT);
19 | }
20 |
21 | log.args('Ti.UI.TextField.inputType', names);
22 |
23 | $.textField.inputType = inputType;
24 | $.textField.blur();
25 | }
26 |
--------------------------------------------------------------------------------
/app/controllers/android/launcher.js:
--------------------------------------------------------------------------------
1 | var log = require('log');
2 |
3 | /**
4 | * I wrap code that executes on creation in a self-executing function just to
5 | * keep it organised, not to protect global scope like it would in alloy.js
6 | */
7 | (function constructor() {
8 |
9 | // If the app was launched with the shortcut it would have this extra metadata
10 | $.feedback.text = Ti.App.Android.launchIntent.hasExtra('sample') ? 'Yes' : 'No';
11 |
12 | })();
13 |
14 | function closeWindow() {
15 | $.win.close();
16 | }
17 |
18 | function installShortcut(e) {
19 |
20 | // Copy the intent used to launch the app
21 | var intentForShortcut = Ti.App.Android.launchIntent;
22 |
23 | // Re-set the action to have the intent be the app entry point
24 | intentForShortcut.action = Ti.Android.ACTION_MAIN;
25 | intentForShortcut.addFlags(Ti.Android.FLAG_ACTIVITY_SINGLE_TOP);
26 |
27 | // Add custom metadata to read when the app is launched from the shortcut.
28 | // See index.js to see how we use this to directly open the launcher sample.
29 | intentForShortcut.putExtra('sample', 'launcher');
30 |
31 | // Create an intent to install the shortcut
32 | var intentToInstallShortcut = Ti.Android.createIntent({
33 | action: 'com.android.launcher.action.INSTALL_SHORTCUT',
34 | });
35 |
36 | // NEW: Link the actual intent for the shortcut
37 | intentToInstallShortcut.putExtra(Ti.Android.EXTRA_SHORTCUT_INTENT, intentForShortcut);
38 |
39 | // Title for the shortcut
40 | intentToInstallShortcut.putExtra(Ti.Android.EXTRA_SHORTCUT_NAME, 'Launch Sample');
41 |
42 | // NEW: Icon for the shortcut
43 | var icon = Ti.Filesystem.getFile(Ti.Filesystem.resourcesDirectory, 'images', 'launcher.png').read();
44 | intentToInstallShortcut.putExtra(Ti.Android.EXTRA_SHORTCUT_ICON, icon);
45 |
46 | // Broadcast the intent
47 | Ti.Android.currentActivity.sendBroadcast(intentToInstallShortcut);
48 |
49 | if (Ti.App.Properties.getBool('installedShortcut', false)) {
50 | alert('You already installed the shortcut before. You might now have an additional one if, unless you have removed the previous one(s).');
51 | } else {
52 | alert('The shortcut has been installed. Force quit the app (3rd button in the system navigation bar, then swipe to close) to try it.');
53 | }
54 |
55 | Ti.App.Properties.setBool('installedShortcut', true);
56 | }
57 |
--------------------------------------------------------------------------------
/app/controllers/android/streetview.js:
--------------------------------------------------------------------------------
1 | function closeWindow() {
2 | $.win.close();
3 | }
4 |
5 | function toggle(e) {
6 | var property = e.source.title;
7 | var value = !(e.source.backgroundColor === Alloy.CFG.brandSuccess);
8 |
9 | $.streetView[property] = value;
10 |
11 | // Change color depending on state
12 | e.source.backgroundColor = value ? Alloy.CFG.brandSuccess : Alloy.CFG.brandSecondary;
13 | }
14 |
--------------------------------------------------------------------------------
/app/controllers/android/tableview.js:
--------------------------------------------------------------------------------
1 | var log = require('log');
2 |
3 | function closeWindow() {
4 | $.win.close();
5 | }
6 |
7 | function toggleSeparatorStyle(e) {
8 |
9 | if ($.tableView.separatorStyle === Ti.UI.TABLE_VIEW_SEPARATOR_STYLE_NONE) {
10 | log.args('Ti.UI.TableView.separatorStyle', 'Ti.UI.TABLE_VIEW_SEPARATOR_STYLE_SINGLE_LINE');
11 | $.tableView.separatorStyle = Ti.UI.TABLE_VIEW_SEPARATOR_STYLE_SINGLE_LINE;
12 | } else {
13 | log.args('Ti.UI.TableView.separatorStyle', 'Ti.UI.TABLE_VIEW_SEPARATOR_STYLE_NONE');
14 | $.tableView.separatorStyle = Ti.UI.TABLE_VIEW_SEPARATOR_STYLE_NONE;
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/app/controllers/android/transitions.js:
--------------------------------------------------------------------------------
1 | var log = require('log');
2 |
3 | function closeWindow() {
4 | $.win.close();
5 | }
6 |
7 | function openWindowA() {
8 |
9 | // For each setting
10 | ['activityExitTransition', 'activityReenterTransition', 'activitySharedElementExitTransition', 'activitySharedElementReenterTransition'].forEach(function(prop) {
11 | var constant = $[prop].getSelectedRow(0).title;
12 |
13 | if (constant.indexOf('TRANSITION_') === -1) {
14 | log.args('Ti.UI.Window.' + prop, constant);
15 |
16 | // We set a global that will be used for the creation-only property in transitions_a.tss
17 | Alloy.Globals[prop] = undefined;
18 |
19 | } else {
20 | log.args('Ti.UI.Window.' + prop, 'Ti.UI.Android.' + constant);
21 | Alloy.Globals[prop] = Ti.UI.Android[constant];
22 | }
23 |
24 | });
25 |
26 | // Open Window A
27 | Alloy.createController('transitions_a').getView().open();
28 | }
29 |
--------------------------------------------------------------------------------
/app/controllers/android/transitions_a.js:
--------------------------------------------------------------------------------
1 | var log = require('log');
2 |
3 | function closeWindow() {
4 | $.win.close();
5 | }
6 |
7 | function openWindowB() {
8 |
9 | // For each setting
10 | ['activityEnterTransition', 'activityReturnTransition', 'activitySharedElementEnterTransition', 'activitySharedElementReturnTransition'].forEach(function(prop) {
11 | var constant = $[prop].getSelectedRow(0).title;
12 |
13 | if (constant.indexOf('TRANSITION_') === -1) {
14 | log.args('Ti.UI.Window.' + prop, constant);
15 |
16 | // We set a global that will be used for the creation-only property in transitions_a.tss
17 | Alloy.Globals[prop] = undefined;
18 |
19 | } else {
20 | log.args('Ti.UI.Window.' + prop, 'Ti.UI.Android.' + constant);
21 | Alloy.Globals[prop] = Ti.UI.Android[constant];
22 | }
23 |
24 | });
25 |
26 | // Get Window B
27 | var win = Alloy.createController('transitions_b').getView();
28 |
29 | // Link shared elements using the transitionName also set in both XML files
30 | win.addSharedElement($.logo, 'logo');
31 | win.addSharedElement($.text, 'text');
32 |
33 | // Open the Window
34 | win.open();
35 | }
36 |
--------------------------------------------------------------------------------
/app/controllers/android/transitions_b.js:
--------------------------------------------------------------------------------
1 | function closeWindow() {
2 | $.win.close();
3 | }
4 |
--------------------------------------------------------------------------------
/app/controllers/console.js:
--------------------------------------------------------------------------------
1 | var log = require('log');
2 |
3 | /**
4 | * I wrap code that executes on creation in a self-executing function just to
5 | * keep it organised, not to protect global scope like it would in alloy.js
6 | */
7 | (function constructor(args) {
8 |
9 | // Show logs from before this controller was created
10 | showLogs();
11 |
12 | // Listen to changes to the logs
13 | log.on('change', showLogs);
14 |
15 | })(arguments[0] || {});
16 |
17 | function showLogs() {
18 | $.log.text = log.history;
19 |
20 | $.scrollView.scrollToBottom();
21 | }
22 |
23 | function clearLogs() {
24 |
25 | // Clear the public property holding the log history
26 | log.history = '';
27 |
28 | showLogs();
29 | }
30 |
--------------------------------------------------------------------------------
/app/controllers/index.js:
--------------------------------------------------------------------------------
1 | var log = require('log');
2 |
3 | var activity;
4 |
5 | /**
6 | * I wrap code that executes on creation in a self-executing function just to
7 | * keep it organised, not to protect global scope like it would in alloy.js
8 | */
9 | (function constructor(args) {
10 |
11 | if (Alloy.Globals.isSupported) {
12 |
13 | if (OS_IOS) {
14 | initActivity();
15 |
16 | if (Alloy.isTablet) {
17 | initMultitasking();
18 | }
19 | }
20 |
21 | if (OS_ANDROID) {
22 | initTabMenus();
23 | initShortcut();
24 | }
25 | }
26 |
27 | // Wait a bit to make it easier to see fullscreen and storyboard changes
28 | setTimeout(function() {
29 |
30 | // Opens either the TabGroup or "Not Supported" Window depending on
31 | // the Alloy.Globals.isSupported flag used in index.xml
32 | $.index.open();
33 |
34 | }, 2000);
35 |
36 | })(arguments[0] || {});
37 |
38 | function onListViewItemclick(e) {
39 | var item = e.section.getItemAt(e.itemIndex);
40 |
41 | // We use classes in index.xml with conditional TSS in index.tss to set this flag
42 | if (item.properties.unsupported) {
43 | return alert('Your device does not meet the requirements for this example.');
44 | }
45 |
46 | var controllerName = e.itemId;
47 |
48 | // Special case. We want to list the Tab sample but it should select the middle tab.
49 | if (controllerName === 'tab') {
50 | $.index.tabs[1].active = true;
51 | return;
52 | }
53 |
54 | openSample(controllerName);
55 | }
56 |
57 | function openSample(controllerName) {
58 | var controller = Alloy.createController(controllerName);
59 |
60 | $.samplesTab.open(controller.getView());
61 | }
62 |
63 | // iOS: Show how the usage of needsSave has changed
64 | function initActivity() {
65 |
66 | activity = Ti.App.iOS.createUserActivity({
67 | activityType: 'com.appcelerator.sample.ti520.tab',
68 | title: Ti.App.name,
69 | userInfo: {
70 | activeTabIndex: 0
71 | }
72 | });
73 |
74 | if (activity.isSupported()) {
75 | activity.becomeCurrent();
76 |
77 | Ti.App.iOS.addEventListener('continueactivity', function(e) {
78 | log.args('Ti.App.iOS:continueactivity', e);
79 |
80 | // Activate the tab active on the other device
81 | if (e.activityType === 'com.appcelerator.sample.ti520.tab') {
82 | $.index.tabs[e.userInfo.activeTabIndex].active = true;
83 | }
84 |
85 | });
86 |
87 | // When a tab receives focus
88 | $.index.addEventListener('focus', function(e) {
89 | var userInfo = {
90 | activeTabIndex: e.index
91 | };
92 |
93 | log.args('Ti.App.iOS.UserActivity.userInfo', userInfo);
94 |
95 | // Update the userInfo here, where before we would need to wait for
96 | // the useractivitywillsave event
97 | activity.userInfo = userInfo;
98 |
99 | // Inform iOS the activity has changed
100 | activity.needsSave = true;
101 | });
102 | }
103 | }
104 |
105 | // iPad: Logs the TabGroup dimensions each time we switch fullscreen, Slide Over or Split View mode
106 | function initMultitasking() {
107 |
108 | function logDimensions(e) {
109 | log.args('Ti.App:' + e.type + ' was fired and our dimensions are:', {
110 | 'Ti.Platform.displayCaps.platformWidth': Ti.Platform.displayCaps.platformWidth,
111 | 'Ti.Platform.displayCaps.platformHeight': Ti.Platform.displayCaps.platformHeight,
112 | '$.index.size.width': $.index.size.width,
113 | '$.index.size.height': $.index.size.height
114 | });
115 | }
116 |
117 | // This event fires when the app was still active in the background when it Slides Over another app
118 | Ti.App.addEventListener('resume', logDimensions);
119 |
120 | // Will (also) fires when:
121 | // 1) This app Slides Over another app
122 | // 2) This app goes from Slide Over to Split View
123 | // 3) This app goes from quarter to half Split View or visa versa
124 | // 4) The user dragged the Split View devider but released it to bounce back to existing mode
125 | // 5) This app goes from Split View to full view (by dragging the devider to the left edge)
126 | // 6) This app goes from Split View to Slide Over (by singletap on devider)
127 | // 7) Another app goes from Slide Over to Split View
128 | //
129 | // It does not fire when:
130 | // 1) Another app goes from Slit View to Slide Over (by singletap on devider)
131 | Ti.App.addEventListener('resumed', logDimensions);
132 |
133 | // 1) Another app starts to Slide Over
134 | // 2) Another app starts to go from right Split View to Slide Over (by singletap on devider)
135 | // 3) The user starts dragging the Split View devider
136 | Ti.App.addEventListener('pause', logDimensions);
137 |
138 | // This event fires when another app is dragged from quarter or half Split View to fullscreen
139 | Ti.App.addEventListener('paused', logDimensions);
140 | }
141 |
142 | // Android: Hack to delegate the creation of the TabGroup's menu to the active tab
143 | function initTabMenus() {
144 |
145 | $.index.addEventListener('open', function(e) {
146 |
147 | $.index.activity.addEventListener('newintent', function(e) {
148 | console.log('newintent from index.js added to tabgroup activity ' + JSON.stringify(e));
149 | });
150 |
151 | $.index.activity.onCreateOptionsMenu = function(e) {
152 |
153 | // Delegate the creation of the menu to the active tab
154 | if ($.index.activeTab.window.activity.onCreateOptionsMenu) {
155 | $.index.activeTab.window.activity.onCreateOptionsMenu(e);
156 | }
157 | };
158 |
159 | });
160 |
161 | // When a tab receives focus
162 | $.index.addEventListener('focus', function(e) {
163 |
164 | // Force the TabGroup's menu to be regenerated
165 | $.index.activity.invalidateOptionsMenu();
166 | });
167 |
168 | }
169 |
170 | // Android: Launch the app via an additional shortcut to a sample (see launcher.js)
171 | function initShortcut() {
172 | var sample = Ti.App.Android.launchIntent.getStringExtra('sample');
173 |
174 | // If we were launched using a shortcut to a specific sample
175 | if (sample) {
176 |
177 | // Wait for the TabGroup to be open
178 | $.index.addEventListener('open', function(e) {
179 | openSample(sample);
180 |
181 | alert('You have used the additional launch shortcut.');
182 | });
183 | }
184 | }
185 |
--------------------------------------------------------------------------------
/app/controllers/ios/appshortcuts.js:
--------------------------------------------------------------------------------
1 | var log = require('log');
2 |
3 | function createShortcut(e) {
4 |
5 | if (Ti.Contacts.hasContactsPermissions()) {
6 | return _createShortcut();
7 | }
8 |
9 | if (Ti.Contacts.contactsAuthorization === Ti.Contacts.AUTHORIZATION_RESTRICTED) {
10 | return alert('Access to contacts has been restricted');
11 | }
12 |
13 | Ti.Contacts.requestContactsPermissions(function(e) {
14 |
15 | if (!e.success) {
16 | return alert(e.error || 'Error #' + code);
17 | }
18 |
19 | _createShortcut();
20 | });
21 | }
22 |
23 | function _createShortcut() {
24 |
25 | Ti.Contacts.showContacts({
26 |
27 | // Called when the user has selected a contact person
28 | selectedPerson: function(e) {
29 | var appShortcuts = Ti.UI.iOS.createApplicationShortcuts();
30 |
31 | // remove previous shortcut of this type, if any
32 | appShortcuts.removeDynamicShortcut('contact');
33 |
34 | // add the new shortcut
35 | appShortcuts.addDynamicShortcut({
36 | itemtype: 'contact',
37 | title: e.person.fullName,
38 | userInfo: {
39 | person: {
40 | fullName: e.person.fullName
41 | }
42 | },
43 |
44 | // use the contact person as the icon
45 | icon: e.person
46 | });
47 |
48 | alert('Now move your app to the background and force touch the app icon to see the contact icon');
49 | }
50 | });
51 | }
52 |
--------------------------------------------------------------------------------
/app/controllers/ios/keyboard.js:
--------------------------------------------------------------------------------
1 | var log = require('log');
2 |
3 | function changeKeyboardType(e) {
4 | var keyboardType = 'KEYBOARD_TYPE_' + e.source.labels[e.index].title;
5 | log.args('keyboardType', 'Ti.UI.' + keyboardType);
6 |
7 | $.textField.keyboardType = Ti.UI[keyboardType];
8 | $.textField.blur();
9 | }
10 |
11 | function changeKeyboardAppearance(e) {
12 | var keyboardAppearance = 'KEYBOARD_APPEARANCE_' + e.source.labels[e.index].title;
13 | log.args('keyboardAppearance', 'Ti.UI.' + keyboardAppearance);
14 |
15 | // Notice that since 5.2 you should use keyboardAppearance instead of appearance
16 | $.textField.keyboardAppearance = Ti.UI[keyboardAppearance];
17 | $.textField.blur();
18 | }
19 |
20 | function changeReturnKeyType(e) {
21 | var returnKeyType = 'RETURNKEY_' + e.source.labels[e.index].title;
22 | log.args('returnKeyType', 'Ti.UI.' + returnKeyType);
23 |
24 | $.textField.returnKeyType = Ti.UI[returnKeyType];
25 | $.textField.blur();
26 | }
27 |
--------------------------------------------------------------------------------
/app/controllers/ios/listview.js:
--------------------------------------------------------------------------------
1 | var log = require('log');
2 |
3 | function enableEdit(e) {
4 | $.win.rightNavButton = $.doneBtn;
5 |
6 | $.listView.editing = true;
7 | }
8 |
9 | function disableEdit(e) {
10 | $.win.rightNavButton = $.editBtn;
11 |
12 | $.listView.editing = false;
13 | }
14 |
15 | function onDrag(e) {
16 | log.args('Ti.UI.ListView:' + e.type, e);
17 | }
18 |
19 | function onInsert(e) {
20 | log.args('Ti.UI.ListView:insert', e);
21 |
22 | var item = e.section.getItemAt(e.itemIndex);
23 |
24 | // We insert a new item AFTER (+1) the selected item
25 | e.section.insertItemsAt(e.itemIndex + 1, [{
26 | properties: {
27 | canInsert: true,
28 | title: 'Inserted after ' + item.properties.title
29 | }
30 | }]);
31 | }
32 |
--------------------------------------------------------------------------------
/app/controllers/ios/livephoto.js:
--------------------------------------------------------------------------------
1 | var log = require('log');
2 |
3 | function openPhotoGallery() {
4 |
5 | Ti.Media.openPhotoGallery({
6 |
7 | // You can not use LIVEPHOTO without also allowing PHOTO
8 | mediaTypes: [Ti.Media.MEDIA_TYPE_LIVEPHOTO, Ti.Media.MEDIA_TYPE_PHOTO],
9 | cancel: handleResponse,
10 | error: handleResponse,
11 | success: handleResponse
12 | });
13 | }
14 |
15 | function handleResponse(e) {
16 | log.args('Ti.Media.openPhotoGallery', e);
17 |
18 | if (!e.success) {
19 | return alert(e.error || 'Error #' + e.code);
20 | }
21 |
22 | if (e.mediaType !== Ti.Media.MEDIA_TYPE_LIVEPHOTO) {
23 | return alert('This should never happen. We required a Live Photo but somehow you selected something else.');
24 | }
25 |
26 | if (!e.livePhoto) {
27 | return alert('This should never happen. If mediaType says you selected a Live Photo it should be there.');
28 | }
29 |
30 | $.livePhotoView.livePhoto = e.livePhoto;
31 |
32 | // Programmatically triggering playback isn't recommended in any other use case
33 | // then when the photo is loaded or slides in to the viewport.
34 | $.livePhotoView.startPlaybackWithStyle(Ti.UI.iOS.LIVEPHOTO_PLAYBACK_STYLE_HINT);
35 | }
36 |
37 | function onLivePhotoViewStartStop(e) {
38 | log.args('Ti.UI.iOS.LivePhotoView:' + e.type, e);
39 | }
40 |
41 | function startPlaybackWithStyle(e) {
42 | var playbackStyle = 'LIVEPHOTO_PLAYBACK_STYLE_' + e.source.labels[e.index].title;
43 | log.args('playbackStyle', 'Ti.UI.iOS.' + playbackStyle);
44 |
45 | $.livePhotoView.startPlaybackWithStyle(Ti.UI.iOS[playbackStyle]);
46 | }
47 |
48 | function stopPlayback() {
49 | $.livePhotoView.stopPlayback();
50 | }
51 |
--------------------------------------------------------------------------------
/app/controllers/ios/menupopup.js:
--------------------------------------------------------------------------------
1 | var log = require('log');
2 |
3 | var timeout;
4 |
5 | function showWithDefaults(e) {
6 | show({
7 | view: e.source
8 | });
9 | }
10 |
11 | function showWithAnimated(e) {
12 | show({
13 | view: e.source,
14 | animated: (e.index === 0)
15 | });
16 | }
17 |
18 | function showWithArrowDirection(e) {
19 | var arrowDirection = 'MENU_POPUP_ARROW_DIRECTION_' + e.source.labels[e.index].title;
20 |
21 | show({
22 | view: e.source,
23 | arrowDirection: Ti.UI.iOS[arrowDirection]
24 | });
25 | }
26 |
27 | function show(params) {
28 |
29 | // if we didn't do so already, clear the timeout to auto-hide
30 | clearTimeout(timeout);
31 |
32 | log.args('Ti.UI.iOS.MenuPopup.show()', stringifyArrowDirection(params));
33 |
34 | $.menu.show(params);
35 |
36 | // To demonstrate isVisible and hide() we set a timeout
37 | timeout = setTimeout(function() {
38 |
39 | var isVisible = $.menu.isVisible();
40 | log.args('Ti.UI.iOS.MenuPopup.isVisible()', isVisible);
41 |
42 | if (isVisible) {
43 | var hideParams = _.pick(params, 'animated');
44 | log.args('Ti.UI.iOS.MenuPopup.hide()', hideParams);
45 |
46 | $.menu.hide(hideParams);
47 | }
48 |
49 | }, 1000);
50 | }
51 |
52 | function onMenuPopupClick(e) {
53 | log.args('Ti.UI.iOS.MenuPopup:click', e);
54 | }
55 |
56 | // Helper to display the constant name instead of its value
57 | function stringifyArrowDirection(params) {
58 | var clone = _.clone(params);
59 |
60 | if (clone.arrowDirection) {
61 |
62 | switch (clone.arrowDirection) {
63 | case Ti.UI.iOS.MENU_POPUP_ARROW_DIRECTION_LEFT:
64 | clone.arrowDirection = 'Ti.UI.iOS.MENU_POPUP_ARROW_DIRECTION_LEFT';
65 | break;
66 | case Ti.UI.iOS.MENU_POPUP_ARROW_DIRECTION_UP:
67 | clone.arrowDirection = 'Ti.UI.iOS.MENU_POPUP_ARROW_DIRECTION_UP';
68 | break;
69 | case Ti.UI.iOS.MENU_POPUP_ARROW_DIRECTION_DOWN:
70 | clone.arrowDirection = 'Ti.UI.iOS.MENU_POPUP_ARROW_DIRECTION_DOWN';
71 | break;
72 | case Ti.UI.iOS.MENU_POPUP_ARROW_DIRECTION_RIGHT:
73 | clone.arrowDirection = 'Ti.UI.iOS.MENU_POPUP_ARROW_DIRECTION_RIGHT';
74 | break;
75 | }
76 | }
77 |
78 | return clone;
79 | }
80 |
--------------------------------------------------------------------------------
/app/controllers/ios/popover.js:
--------------------------------------------------------------------------------
1 | function openPopover(e) {
2 |
3 | $.popover.backgroundColor = (e.index === 1) ? Alloy.CFG.brandPrimary : '';
4 |
5 | $.popover.show({
6 | view: e.source,
7 | rect: {
8 |
9 | // This will position the arrow on 1/4th or 3/4th of the ButtonBar width
10 | x: e.source.size.width * ((e.index === 1) ? 0.75 : 0.25),
11 |
12 | // This will position the arrow at the bottom of the ButtonBar
13 | y: e.source.size.height
14 | }
15 | });
16 | }
17 |
--------------------------------------------------------------------------------
/app/controllers/ios/scrollview.js:
--------------------------------------------------------------------------------
1 | var log = require('log');
2 |
3 | function onScroll(e) {
4 | log.args('Ti.UI.ScrollView:scroll', e);
5 | }
6 |
--------------------------------------------------------------------------------
/app/controllers/ios/touch.js:
--------------------------------------------------------------------------------
1 | var log = require('log');
2 |
3 | var EVENTS = ['touchstart', 'touchend', 'click', 'touchmove', 'dblclick', 'touchcancel'];
4 | var PROPS = ['x', 'y', 'force', 'maximumPossibleForce', 'timestamp', 'altitudeAngle'];
5 |
6 | /**
7 | * I wrap code that executes on creation in a self-executing function just to
8 | * keep it organised, not to protect global scope like it would in alloy.js
9 | */
10 |
11 | (function constructor() {
12 |
13 | // For each event
14 | EVENTS.forEach(function(name) {
15 |
16 | $.touchArea.addEventListener(name, function(e) {
17 |
18 | if (e.maximumPossibleForce === undefined) {
19 | return alert('This should never happen. Force Touch is supported by maximumPossibleForce is undefined.');
20 | }
21 |
22 | // Show property values
23 | $.feedback.text = 'type: ' + e.type + '\n' + PROPS.map(function(prop) {
24 | return prop + ': ' + e[prop];
25 | }).join('\n');
26 |
27 | // the harder you press, the less opaque the view becomes
28 | $.touchArea.opacity = 1 - (e.force / e.maximumPossibleForce);
29 | });
30 |
31 | });
32 |
33 | })();
34 |
--------------------------------------------------------------------------------
/app/controllers/ios/watchos.js:
--------------------------------------------------------------------------------
1 | var log = require('log');
2 |
3 | var PROPS = ['isSupported', 'isPaired', 'isReachable', 'isWatchAppInstalled'];
4 |
5 | /**
6 | * I wrap code that executes on creation in a self-executing function just to
7 | * keep it organised, not to protect global scope like it would in alloy.js
8 | */
9 | (function constructor() {
10 |
11 | if (Ti.WatchSession.isSupported) {
12 | Ti.WatchSession.activateSession();
13 | }
14 |
15 | // Show properties values
16 | $.feedback.text = PROPS.map(function(prop) {
17 | return 'Ti.WatchSession.' + prop + ':\n' + Ti.WatchSession[prop];
18 | }).join('\n\n');
19 |
20 | })();
21 |
--------------------------------------------------------------------------------
/app/controllers/tab.js:
--------------------------------------------------------------------------------
1 | var log = require('log');
2 |
3 | function onTabSelection(e) {
4 | log.args('Ti.UI.Tab:' + e.type, e);
5 | }
6 |
--------------------------------------------------------------------------------
/app/lib/log.js:
--------------------------------------------------------------------------------
1 | /* global ENV_PROD */
2 |
3 | var moment = require('alloy/moment');
4 |
5 | var Log = module.exports = _.extend({}, Backbone.Events);
6 |
7 | Log.history = '';
8 |
9 | Log.args = function() {
10 | _log(arguments, {
11 | withoutApis: true
12 | });
13 | };
14 |
15 | Log.argsWithApis = function() {
16 | _log(arguments, {
17 | withoutApis: false
18 | });
19 | };
20 |
21 | function _log(args, opts) {
22 | args = Array.prototype.slice.call(args);
23 | opts = opts || {};
24 |
25 | // Stringify non-strings
26 | args = args.map(function(arg) {
27 |
28 | if (typeof arg !== 'string') {
29 | arg = JSON.stringify(arg, opts.withoutApis ? function(key, val) {
30 |
31 | if (typeof val === 'object' && val !== null && val.apiName) {
32 | return '[' + val.apiName + ']' + (val.id ? ' #' + val.id : '');
33 | } else {
34 | return val;
35 | }
36 |
37 | } : null, 2);
38 | }
39 |
40 | return arg;
41 | });
42 |
43 | var message = args.join(' ');
44 |
45 | // Use error-level for production or they will not show in Xcode console
46 | console[ENV_PROD ? 'error' : 'info'](message);
47 |
48 | // Add the message to a global variable for controllers/console.js to use
49 | Log.history = (Log.history || '') + '[' + moment().format('HH:mm:ss.SS') + '] ' + message + '\n\n';
50 |
51 | // Trigger an event for controllers/console.js to listen to and display the log
52 | Log.trigger('change');
53 | }
54 |
--------------------------------------------------------------------------------
/app/platform/android/res/drawable-hdpi/appicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appcelerator-developer-relations/appc-sample-ti520/e91e8b14182114b2912d60cd4604dc06170df8e7/app/platform/android/res/drawable-hdpi/appicon.png
--------------------------------------------------------------------------------
/app/platform/android/res/drawable-hdpi/background.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appcelerator-developer-relations/appc-sample-ti520/e91e8b14182114b2912d60cd4604dc06170df8e7/app/platform/android/res/drawable-hdpi/background.9.png
--------------------------------------------------------------------------------
/app/platform/android/res/drawable-mdpi/appicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appcelerator-developer-relations/appc-sample-ti520/e91e8b14182114b2912d60cd4604dc06170df8e7/app/platform/android/res/drawable-mdpi/appicon.png
--------------------------------------------------------------------------------
/app/platform/android/res/drawable-mdpi/background.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appcelerator-developer-relations/appc-sample-ti520/e91e8b14182114b2912d60cd4604dc06170df8e7/app/platform/android/res/drawable-mdpi/background.9.png
--------------------------------------------------------------------------------
/app/platform/android/res/drawable-xhdpi/appicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appcelerator-developer-relations/appc-sample-ti520/e91e8b14182114b2912d60cd4604dc06170df8e7/app/platform/android/res/drawable-xhdpi/appicon.png
--------------------------------------------------------------------------------
/app/platform/android/res/drawable-xhdpi/background.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appcelerator-developer-relations/appc-sample-ti520/e91e8b14182114b2912d60cd4604dc06170df8e7/app/platform/android/res/drawable-xhdpi/background.9.png
--------------------------------------------------------------------------------
/app/platform/android/res/drawable-xxhdpi/appicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appcelerator-developer-relations/appc-sample-ti520/e91e8b14182114b2912d60cd4604dc06170df8e7/app/platform/android/res/drawable-xxhdpi/appicon.png
--------------------------------------------------------------------------------
/app/platform/android/res/drawable-xxhdpi/background.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appcelerator-developer-relations/appc-sample-ti520/e91e8b14182114b2912d60cd4604dc06170df8e7/app/platform/android/res/drawable-xxhdpi/background.9.png
--------------------------------------------------------------------------------
/app/platform/android/res/values/custom_theme.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
--------------------------------------------------------------------------------
/app/platform/ios/_LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/app/styles/android/keyboard.tss:
--------------------------------------------------------------------------------
1 | 'Window': {
2 |
3 | // Hide the softkeyboard when the Window opens (and the field receives focus)
4 | windowSoftInputMode: Ti.UI.Android.SOFT_INPUT_STATE_HIDDEN
5 | }
6 |
--------------------------------------------------------------------------------
/app/styles/android/streetview.tss:
--------------------------------------------------------------------------------
1 | '#streetView': {
2 |
3 | // We can set the position (but not the heading)
4 | position: {
5 | latitude: 37.3676332,
6 | longitude: -121.9139205
7 | }
8 | }
9 |
10 | '.buttons': {
11 | top: 0,
12 | right: 10,
13 | width: Ti.UI.SIZE,
14 | height: Ti.UI.SIZE,
15 |
16 | layout: 'vertical'
17 | }
18 |
19 | 'Button': {
20 | top: 10,
21 | right: 0,
22 | width: Ti.UI.SIZE,
23 |
24 | backgroundColor: Alloy.CFG.brandSuccess
25 | }
26 |
--------------------------------------------------------------------------------
/app/styles/android/transitions_a.tss:
--------------------------------------------------------------------------------
1 | 'Window' : {
2 |
3 | // See the XML for the descriptions
4 | // These are creation-only so we use Alloy.Globals to make them configurable
5 | // FIXME: https://jira.appcelerator.org/browse/ALOY-1316
6 | /*activityExitTransition: Alloy.Globals.activityExitTransition,*/
7 | /*activityReenterTransition: Alloy.Globals.activityReenterTransition,*/
8 |
9 | activityExitTransition: Titanium.UI.Android.TRANSITION_NONE,
10 | activityReenterTransition: Titanium.UI.Android.TRANSITION_NONE,
11 |
12 | activitySharedElementExitTransition: Alloy.Globals.activitySharedElementExitTransition,
13 | activitySharedElementReenterTransition: Alloy.Globals.activitySharedElementReenterTransition
14 | }
15 |
16 | 'ImageView': {
17 | width: 50,
18 | backgroundColor: 'white'
19 | }
20 |
--------------------------------------------------------------------------------
/app/styles/android/transitions_b.tss:
--------------------------------------------------------------------------------
1 | 'Window': {
2 |
3 | // See the XML for the descriptions
4 | // These are creation-only so we use Alloy.Globals to make them configurable
5 | // FIXME: https://jira.appcelerator.org/browse/ALOY-1316
6 | activityEnterTransition: Alloy.Globals.activityEnterTransition,
7 | activityReturnTransition: Alloy.Globals.activityReturnTransition,
8 | activitySharedElementEnterTransition: Alloy.Globals.activitySharedElementEnterTransition,
9 | activitySharedElementReturnTransition: Alloy.Globals.activitySharedElementReturnTransition
10 | }
11 |
12 | 'ImageView': {
13 | width: Ti.UI.FILL,
14 | backgroundColor: 'white'
15 | }
16 |
--------------------------------------------------------------------------------
/app/styles/app.tss:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | This is your global styles file. Selectors and rules you define
4 | here will be applied throughout your app. However, these rules
5 | have the lowest priority of any style settings.
6 |
7 | For more information, see the 'Style Priorities' section of
8 | http://docs.appcelerator.com/titanium/latest/#!/guide/Alloy_Styles_and_Themes
9 |
10 | For example, the following would apply to all labels, windows,
11 | and text fields (depending on platform) in your app unless you
12 | overrode the settings with other TSS, XML, or JS settings:
13 |
14 | */
15 |
16 | 'TabGroup[platform=ios]': {
17 |
18 | // by setting both two white you get a brighter kind of white
19 | backgroundColor: 'green',
20 | tabsBackgroundColor: 'white',
21 |
22 | tabsTintColor: Alloy.CFG.brandPrimary
23 | }
24 |
25 | 'Tab[platform=ios]': {
26 | icon: '/images/tabIcon.png'
27 | }
28 |
29 | 'Window[platform=ios]': {
30 |
31 | // white background instead of default transparent or black
32 | backgroundColor: '#fff',
33 |
34 | // Style the TabGroup's navigation bar
35 | barColor: Alloy.CFG.brandPrimary,
36 | navTintColor: '#FFF',
37 | translucent: false,
38 | titleAttributes: {
39 | color: '#FFF'
40 | }
41 | }
42 |
43 | 'Button': {
44 | width: 280
45 | }
46 |
47 | 'ButtonBar': {
48 | width: 280
49 | }
50 |
51 | 'TabbedBar': {
52 | width: 280
53 | }
54 |
55 | 'TextField': {
56 | width: 280
57 | }
58 |
59 | 'ProgressBar': {
60 | width: 280
61 | }
62 |
63 | 'Picker': {
64 | width: 280
65 | }
66 |
67 | // Make Buttons stand out a bit more on iOS
68 | 'Button[platform=ios]': {
69 | borderWidth: 1,
70 | borderColor: '#0071ff',
71 | borderRadius: 4
72 | }
73 |
74 | // Make TextFields stand out a bit more on iOS
75 | 'TextField[platform=ios]': {
76 | height: 30,
77 | paddingLeft: 5,
78 | paddingRight: 5,
79 | borderWidth: 1,
80 | borderColor: '#0071ff',
81 | borderRadius: 4
82 | }
83 |
84 | // Make all ScrollViews scroll vertical
85 | 'ScrollView': {
86 | contentWidth: Ti.UI.FILL,
87 | contentHeight: Ti.UI.SIZE,
88 |
89 | scrollType: 'vertical'
90 | }
91 |
92 | 'MenuItem': {
93 | showAsAction: Ti.Android.SHOW_AS_ACTION_ALWAYS
94 | }
95 |
96 | // A vertical layout with padding
97 | '.vbox': {
98 | layout: 'vertical',
99 | top: 20,
100 | right: 20,
101 | bottom: 20,
102 | left: 20,
103 |
104 | // Because we use both top and bottom height would default to the parent height
105 | height: Ti.UI.SIZE
106 | }
107 |
108 | '.tpad-s': {
109 | top: 10
110 | }
111 |
112 | '.tpad': {
113 | top: 20
114 | }
115 |
116 | '.tpad-l': {
117 | top: 40
118 | }
119 |
120 | '.help': {
121 | color: '#999',
122 | font: {
123 | fontSize: 13
124 | },
125 | textAlign: Ti.UI.TEXT_ALIGNMENT_CENTER
126 | }
127 |
--------------------------------------------------------------------------------
/app/styles/console.tss:
--------------------------------------------------------------------------------
1 | 'ScrollView': {
2 | contentWidth: Ti.UI.FILL,
3 | contentHeight: Ti.UI.SIZE
4 | }
5 |
6 | 'Label': {
7 | top: 10,
8 | right: 10,
9 | left: 10,
10 |
11 | width: Ti.UI.FILL,
12 | height: Ti.UI.SIZE,
13 |
14 | font: {
15 | fontFamily: 'monospace',
16 | fontSize: 13
17 | }
18 | }
--------------------------------------------------------------------------------
/app/styles/index.tss:
--------------------------------------------------------------------------------
1 | 'ItemTemplate': {
2 | height: 50
3 | }
4 |
5 | '.item': {
6 | height: 25
7 | }
8 |
9 | '.item[platform=ios]': {
10 | left: 15
11 | }
12 |
13 | '.item[platform=android]': {
14 | left: 5
15 | }
16 |
17 | '.itemTitle': {
18 | top: 0
19 | }
20 |
21 | '.itemSubtitle': {
22 | top: 25,
23 | color: 'gray'
24 | }
25 |
26 | '.ios[platform=!ios]': {
27 | unsupported: true
28 | }
29 |
30 | '.tablet[formFactor=!tablet]': {
31 | unsupported: true
32 | }
33 |
34 | '.android[platform=!android]': {
35 | unsupported: true
36 | }
37 |
38 | '.forcetouch[if=!Alloy.Globals.isForceTouchSupported]': {
39 | unsupported: true
40 | }
41 |
42 | '.watch[if=!Alloy.Globals.isWatchSupported]': {
43 | unsupported: true
44 | }
45 |
46 | '.unsupported': {
47 |
48 | // Add some margin left and right
49 | left: 20,
50 | right: 20,
51 |
52 | textAlign: Ti.UI.TEXT_ALIGNMENT_CENTER
53 | }
54 |
--------------------------------------------------------------------------------
/app/styles/ios/listview.tss:
--------------------------------------------------------------------------------
1 | 'ItemTemplate': {
2 | height: Ti.UI.SIZE
3 | }
4 |
5 | '.listHelp': {
6 | top: 10,
7 | right: 10,
8 | bottom: 10,
9 | left: 15,
10 |
11 | height: Ti.UI.SIZE
12 | }
13 |
--------------------------------------------------------------------------------
/app/styles/ios/livephoto.tss:
--------------------------------------------------------------------------------
1 | 'LivePhotoView': {
2 | width: 280,
3 | height: 280,
4 | backgroundColor: '#CCC'
5 | }
6 |
--------------------------------------------------------------------------------
/app/styles/ios/progressbar.tss:
--------------------------------------------------------------------------------
1 | 'ProgressBar': {
2 | value: 0.33,
3 |
4 | color: 'blue', // message color
5 | tintColor: 'green', // completed part
6 | trackTintColor: 'red', // uncompleted part
7 |
8 | // FIXME: https://jira.appcelerator.org/browse/TIMOB-20404
9 | bottom: 20,
10 | height: Ti.UI.SIZE
11 | }
12 |
--------------------------------------------------------------------------------
/app/styles/ios/touch.tss:
--------------------------------------------------------------------------------
1 | '#touchArea': {
2 | width: 280,
3 | height: 280,
4 | backgroundColor: '#000',
5 | opacity: 1
6 | }
7 |
8 | '#feedback': {
9 | width: 280,
10 | textAlign: Ti.UI.TEXT_ALIGNMENT_LEFT,
11 | }
12 |
--------------------------------------------------------------------------------
/app/styles/ios/window.tss:
--------------------------------------------------------------------------------
1 | 'Window': {
2 | swipeToClose: false
3 | }
4 |
--------------------------------------------------------------------------------
/app/styles/tab.tss:
--------------------------------------------------------------------------------
1 | 'Tab': {
2 | iconInsets: {
3 | top: 5
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/app/views/android/keyboard.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/app/views/android/launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/app/views/android/streetview.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/app/views/android/tableview.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/app/views/android/transitions.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/app/views/android/transitions_a.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/app/views/android/transitions_b.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/app/views/console.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/app/views/index.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/app/views/ios/appshortcuts.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/views/ios/keyboard.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/app/views/ios/listview.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/app/views/ios/livephoto.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/app/views/ios/menupopup.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 | Option A
40 | Option B
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/app/views/ios/popover.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | >
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/app/views/ios/progressbar.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | >
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/app/views/ios/scrollview.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/app/views/ios/touch.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/app/views/ios/watchos.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/app/views/ios/window.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/views/tab.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | >
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/docs/android.md:
--------------------------------------------------------------------------------
1 | # Titanium 5.2.0: Wrap-up for Android
2 |
3 | This is our final walkthrough on the [Sample App](http://github.com/appcelerator-developer-relations/appc-sample-ti520) for [Titanium 5.2.0](http://www.appcelerator.com/blog/2016/02/ga-release-of-cli-5-2-titanium-5-2-and-studio-4-5/) as we wrap up with the remaining new features and changes for Android:
4 |
5 | [](https://www.youtube.com/watch?v=6UG8VwgoFOk)
6 |
7 | * [TextField inputType](#textfield-inputtype)
8 | * [Launcher Shortcuts](#launcher-shortcuts)
9 | * [TableView separatorStyle](#tableview-separatorstyle)
10 | * [Fullscreen Splash Image](#fullscreen-splash-image)
11 | * [Renamed APIs](#renamed-apis)
12 |
13 | ## Textfield inputType
14 |
15 | You could already set the [keyboardType](http://docs.appcelerator.com/platform/latest/#!/api/Titanium.UI.TextField-property-inputType) for a TextField, but even the [KEYBOARD\_TYPE\_NUMBER_PAD](http://docs.appcelerator.com/platform/latest/#!/api/Titanium.UI-property-KEYBOARD_TYPE_NUMBER_PAD) still included other characters than just numbers and does not impose any limit on hardware keyboards.
16 |
17 | The new [inputType](http://docs.appcelerator.com/platform/latest/#!/api/Titanium.UI.TextField-property-inputType) allows you to the specifically allow only numbers or numbers and text. It will automatically override the right keyboardType for you.
18 |
19 | The sample [allows](../app/views/android/keyboard.xml) you to enable either or both input types to see the effect.
20 |
21 | ## Launcher Shortcuts
22 |
23 | [Ti.Android.Intent.putExra()](http://docs.appcelerator.com/platform/latest/#!/api/Titanium.Android.Intent-method-putExtra) now accepts an [intent](http://docs.appcelerator.com/platform/latest/#!/api/Titanium.Android-property-EXTRA_SHORTCUT_INTENT) or [icon](http://docs.appcelerator.com/platform/latest/#!/api/Titanium.Android-property-EXTRA_SHORTCUT_ICON). Among other possible use cases, this allows you to create an intent to install additional launch shortcuts for specific activities within your app, each with a unique icon, title and extras to identify the desired action.
24 |
25 | The sample demonstrates how to create this intent in the [launcher.js](../app/controllers/android/launcher.js) controller, while the [index.js](../app/controllers/index.js#L170) shows how to retrieve extras from the launch intent to take appropriate action.
26 |
27 | > **NOTE:** It's a [known issue](https://jira.appcelerator.org/browse/TIMOB-20459) that if the app is running in the background, there is no way to know which intent (e.g. a launch shortcut) caused it to resume.
28 |
29 | ## TableView separatorStyle
30 |
31 | [Ti.UI.TableView.separatorStyle](http://docs.appcelerator.com/platform/latest/#!/api/Titanium.UI.TableView-property-separatorStyle) was already supported for iOS and MobileWeb, but now you can hide the separator line on Android as well.
32 |
33 | Tap anywhere in the Sample's TableView to [toggle the style](../app/controllers/android/tableview.js).
34 |
35 | > **NOTE:** Support for ListView is [yet to be added](https://jira.appcelerator.org/browse/TIMOB-19141).
36 |
37 | ## Fullscreen Splash Image
38 |
39 | If you set the `` option in [tiapp.xml](../tiapp.xml#L14) to `true` this will now show the splash image fullscreen. The Android top status bar and bottom soft navigation bar will be hidden:
40 |
41 | [](https://www.youtube.com/watch?v=tF042Nl99UA)
42 |
43 | Be aware that this will also default your app to use the `Theme.AppCompat.NoTitleBar.Fullscreen` theme [introduced in 5.0](http://docs.appcelerator.com/platform/latest/#!/guide/Titanium_SDK_5.0.0_Release_Note-section-46239777_TitaniumSDK5.0.0ReleaseNote-TitaniumThemes). If you want a fullscreen splash image but still show the status bar and Action Bar in the app itself, you will have to manually set the theme. The sample app [uses a custom theme](../tiapp.xml#L98), but you can also use the default like this:
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 | ## Renamed APIs
52 |
53 | Finally, I'd like to remind you again of some properties and methods that we have deprecated and renamed to improve the consistency of our API. The old ones will be removed in Titanium 6.0.
54 |
55 | | Old | New |
56 | | --- | --- |
57 | | `Ti.UI.Tab.(blur/focus)` | `Ti.UI.Tab.(un)?selected`
58 | | `Ti.UI.TabGroup.(un)?selected` | `Ti.UI.TabGroup.(blur/focus)`
59 | | `Ti.UI.(TextArea/Field).appearance` | `Ti.UI.(TextArea/Field).keyboardAppearance`
60 | | `Ti.UI.KEYBOARD_*` | `Ti.UI.KEYBOARD_TYPE_*` and `Ti.UI.KEYBOARD_APPEARANCE_*`
61 | | `Ti.UI.KEYBOARD_APPEARANCE_ALERT` | `Ti.UI.KEYBOARD_APPEARANCE_DARK`
62 | | `Ti.Calendar.STATUS_CANCELLED` | `Ti.Calendar.STATUS_CANCELED`
63 | | `Ti.Calendar.eventsAuthorization` | `Ti.Calendar.calendarAuthorization`
64 | | `Ti.Calendar.CAMERA_AUTHORIZATION_NOT_DETERMINED` | `Ti.Calendar.CAMERA_AUTHORIZATION_UNKNOWN`
65 | | `Ti.Media.cameraAuthorizationStatus` | `Ti.Media.cameraAuthorization`
66 |
67 | Code Strong 🚀
68 |
--------------------------------------------------------------------------------
/docs/assets/avd.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appcelerator-developer-relations/appc-sample-ti520/e91e8b14182114b2912d60cd4604dc06170df8e7/docs/assets/avd.png
--------------------------------------------------------------------------------
/docs/assets/image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appcelerator-developer-relations/appc-sample-ti520/e91e8b14182114b2912d60cd4604dc06170df8e7/docs/assets/image.png
--------------------------------------------------------------------------------
/docs/assets/insertion.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appcelerator-developer-relations/appc-sample-ti520/e91e8b14182114b2912d60cd4604dc06170df8e7/docs/assets/insertion.png
--------------------------------------------------------------------------------
/docs/assets/ipadpro.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appcelerator-developer-relations/appc-sample-ti520/e91e8b14182114b2912d60cd4604dc06170df8e7/docs/assets/ipadpro.png
--------------------------------------------------------------------------------
/docs/assets/launch-builtin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appcelerator-developer-relations/appc-sample-ti520/e91e8b14182114b2912d60cd4604dc06170df8e7/docs/assets/launch-builtin.png
--------------------------------------------------------------------------------
/docs/assets/launch-custom.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appcelerator-developer-relations/appc-sample-ti520/e91e8b14182114b2912d60cd4604dc06170df8e7/docs/assets/launch-custom.png
--------------------------------------------------------------------------------
/docs/assets/menupopup.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appcelerator-developer-relations/appc-sample-ti520/e91e8b14182114b2912d60cd4604dc06170df8e7/docs/assets/menupopup.png
--------------------------------------------------------------------------------
/docs/assets/module.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appcelerator-developer-relations/appc-sample-ti520/e91e8b14182114b2912d60cd4604dc06170df8e7/docs/assets/module.png
--------------------------------------------------------------------------------
/docs/assets/screenshots.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appcelerator-developer-relations/appc-sample-ti520/e91e8b14182114b2912d60cd4604dc06170df8e7/docs/assets/screenshots.png
--------------------------------------------------------------------------------
/docs/assets/simpholders.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appcelerator-developer-relations/appc-sample-ti520/e91e8b14182114b2912d60cd4604dc06170df8e7/docs/assets/simpholders.png
--------------------------------------------------------------------------------
/docs/assets/splitview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appcelerator-developer-relations/appc-sample-ti520/e91e8b14182114b2912d60cd4604dc06170df8e7/docs/assets/splitview.png
--------------------------------------------------------------------------------
/docs/assets/streetview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appcelerator-developer-relations/appc-sample-ti520/e91e8b14182114b2912d60cd4604dc06170df8e7/docs/assets/streetview.png
--------------------------------------------------------------------------------
/docs/assets/tab.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appcelerator-developer-relations/appc-sample-ti520/e91e8b14182114b2912d60cd4604dc06170df8e7/docs/assets/tab.png
--------------------------------------------------------------------------------
/docs/assets/transitions.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appcelerator-developer-relations/appc-sample-ti520/e91e8b14182114b2912d60cd4604dc06170df8e7/docs/assets/transitions.png
--------------------------------------------------------------------------------
/docs/ios.md:
--------------------------------------------------------------------------------
1 | # Titanium 5.2.0: Wrap-up for iOS
2 |
3 | Let's wrap-up our tour through the [Sample App](http://github.com/appcelerator-developer-relations/appc-sample-ti520) for [Titanium 5.2.0](http://www.appcelerator.com/blog/2016/02/ga-release-of-cli-5-2-titanium-5-2-and-studio-4-5/) before 5.2.1 arrives. I'll briefly introduce you to some of the remaining new features and changes.
4 |
5 | Let's start with iOS:
6 |
7 | [](https://www.youtube.com/watch?v=vGZ4su0TZts)
8 |
9 | * [MenuPopup](#menupopup)
10 | * [3D Touch & Apple Pencil Events](#3d-touch--apple-pencil-events)
11 | * [WatchOS2 Swift Template](#watchos2-swift-template)
12 | * [ListView Insertion Control & Drag Events](#listview-insertion-control--drag-events)
13 | * [Tab Icon Insets](#tab-icon-insets)
14 | * [Updating User Activities](#updating-user-activities)
15 | * [Small but not forgotten](#small-but-not-forgotten)
16 | * [Renamed APIs](#renamed-apis)
17 |
18 | ## MenuPopup
19 |
20 | The last remaining new UI component added in this release is [Ti.UI.iOS.MenuPopup](http://docs.appcelerator.com/platform/latest/#!/api/Titanium.UI.iOS.MenuPopup) which implements [UIMenuController](https://developer.apple.com/library/prerelease/ios/documentation/iPhone/Reference/UIMenuController_Class/index.html). In TextFields and TextAreas these popup automatically with edit options like cut, copy, paste etc. Alloy support is [under way](https://jira.appcelerator.org/browse/ALOY-1357), so open the [menupopup.js](../app/controllers/ios/menupopup.js) controller to see how we instantiate and configure this menu to show with any view.
21 |
22 | 
23 |
24 | ## 3D Touch & Apple Pencil Events
25 |
26 | We've added new events to the [touch*](http://docs.appcelerator.com/platform/latest/#!/api/Titanium.UI.View-event-touchstart), `click` and `dblclick` events for use with 3D Touch and Apple Pencil. Playback the above video to see how the [touch.xml](../app/views/ios/touch.xml) view allows you to try them out with some nice visual feedback using `force` and `maximumPossibleForce`.
27 |
28 | ## WatchOS2 Swift Template
29 |
30 | When you add an WatchOS2 extension to your Titanium iOS app using `appc create` you will now get a [Swift template](../extensions/Ti 5.2.0/Ti 5.2.0 WatchKit Extension). The Objective-C template is still available by using `appc create -t applewatch --template watchos2-objc`. We've also cleaned up the template to include nothing more than Xcode does, except for some [icons](../extensions/Ti 5.2.0/Ti 5.2.0 WatchKit App/Assets.xcassets/AppIcon.appiconset/) and an example of how to [initiate a Watch Connectivity Session](../extensions/Ti 5.2.0/Ti 5.2.0 WatchKit Extension/InterfaceController.m#L22-L29).
31 |
32 | The sample comes with the default WatchOS2 extension and the [watchos.js](../app/controllers/ios/watchos.js) controller lets you confirm the Watch Connectivity Session has been established.
33 |
34 | ## ListView Insertion Control & Drag Events
35 |
36 | As the video demonstrates, you can now enable the [Insertion control](https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/TableView_iPhone/ManageInsertDeleteRow/ManageInsertDeleteRow.html) just like you could already enable the Deletion control. Identical to [delete](http://docs.appcelerator.com/platform/latest/#!/api/Titanium.UI.ListView-event-delete), you will need to listen to the ([undocumented](https://jira.appcelerator.org/browse/TIDOC-2481)) `insert` event to do the actual insert as demonstrated in the [listview.js](../app/controllers/ios/listview.js) controller.
37 |
38 | 
39 |
40 | There's two more new events. Like TableView and ScrollView, ListView now also has `dragstart` and `dragend` events. The sample demonstrates both.
41 |
42 | ## Tab Icon Insets
43 |
44 | If you don't give your tab a title, the icon would still show at the same place to line up with other tabs that might still have a title. You can now [set insets](../app/styles/tab.tss) to shift the icon:
45 |
46 | 
47 |
48 | ## Updating User Activities
49 |
50 | Finally, we need to talk about `Ti.App.iOS.UserActivity`. Originally we modelled this very close to the iOS API. To update an activity you would do set its `needsSave` property to `true` and then wait for the `useractivitywillsave` event to do the actual update. We've now simplified this. You'll make the changes right away and then set the `needsSave` property to inform iOS, as demonstrated in [index.js](../app/controllers/index.js#L63).
51 |
52 | ## Small but not forgotten
53 | But let's not forget that with Titanium 5.2.0 for iOS you can also:
54 |
55 | * [Set the color](../app/styles/ios/progressbar.tss#L6) of the uncompleted track of an `Ti.UI.ProgressBar`.
56 | * [Set the backgroundColor](../app/controllers/ios/popover.js#L3) of `Ti.UI.iPad.Popover` so that its arrow can match the backgroundColor of the ContentView.
57 | * [Prevent](../app/styles/ios/window.tss) a `Ti.UI.Window` inside a `Ti.UI.iOS.NavigationWindow` to be closed by swiping form the left edge of the screen.
58 | * [Use](../app/controllers/ios/appshortcuts.js#L45) a `Ti.Contacts.Person` for the icon of `Ti.UI.iOS.ApplicationShortcuts` to display their photo or initials.
59 | * [Listen to the scroll-event](../app/views/ios/scrollview.xml) of a `Ti.UI.ScrollView` to get the `contentSize`, just like with a TableView.
60 | * [Use two new keyboard-types](../app/views/ios/keyboard.xml) and a a new *Continue* return key type in TextFields and TextAreas.
61 |
62 | ## Renamed APIs
63 |
64 | We've also deprecated and renamed some APIs to improve the consistency of our APIs. The old will be removed in Titanium 6.0.
65 |
66 | | Old | New |
67 | | --- | --- |
68 | | `Ti.UI.Tab.(blur/focus)` | `Ti.UI.Tab.(un)?selected`
69 | | `Ti.UI.TabGroup.(un)?selected` | `Ti.UI.TabGroup.(blur/focus)`
70 | | `Ti.UI.(TextArea/Field).appearance` | `Ti.UI.(TextArea/Field).keyboardAppearance`
71 | | `Ti.UI.KEYBOARD_*` | `Ti.UI.KEYBOARD_TYPE_*` and `Ti.UI.KEYBOARD_APPEARANCE_*`
72 | | `Ti.UI.KEYBOARD_APPEARANCE_ALERT` | `Ti.UI.KEYBOARD_APPEARANCE_DARK`
73 | | `Ti.Calendar.STATUS_CANCELLED` | `Ti.Calendar.STATUS_CANCELED`
74 | | `Ti.Calendar.eventsAuthorization` | `Ti.Calendar.calendarAuthorization`
75 | | `Ti.Calendar.CAMERA_AUTHORIZATION_NOT_DETERMINED` | `Ti.Calendar.CAMERA_AUTHORIZATION_UNKNOWN`
76 | | `Ti.Media.cameraAuthorizationStatus` | `Ti.Media.cameraAuthorization`
77 |
78 | Code Strong 🚀
79 |
--------------------------------------------------------------------------------
/docs/launchfiles.md:
--------------------------------------------------------------------------------
1 | # Titanium 5.2.0: Launch Files, iPad Pro, Slide Over and Split View
2 |
3 | With iOS 9 Apple introduced [Slide Over and Split View](https://developer.apple.com/library/prerelease/ios/documentation/WindowsViews/Conceptual/AdoptingMultitaskingOniPad/QuickStartForSlideOverAndSplitView.html) for multitasking on eligible iPad models. You can now enable these new features for your apps in [Titanium 5.2.0](http://www.appcelerator.com/blog/2016/02/ga-release-of-cli-5-2-titanium-5-2-and-studio-4-5/).
4 |
5 | In this blog post I'll walk you through all of this using the new [Titanium 5.2.0 Sample App](http://github.com/appcelerator-developer-relations/appc-sample-ti520):
6 |
7 | [](https://github.com/appcelerator-developer-relations/appc-sample-ti520)
8 |
9 | ## Not a small thing
10 |
11 | Supporting these new features actually was quite an undertaking. We needed to refactor our custom layout engine to use [Auto Layout](https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/AutolayoutPG/index.html), which we did for Titanium 5.1.0 as an [opt-in](http://docs.appcelerator.com/platform/latest/#!/guide/Titanium_SDK_5.1.0_Release_Note-section-46239771_TitaniumSDK5.1.0ReleaseNote-AutoLayout). The other ingredient were [Launch Files](https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/MobileHIG/LaunchImages.html), now available in Titanium 5.2.0. This also gets us support for the [iPad Pro](http://www.apple.com/ipad-pro/), which no longer supports Launch Images.
12 |
13 | ## What are Launch Files?
14 |
15 | Until now, you used to create a bunch of `Default*.png` Launch Images. In iOS 8 Apple introduced [Launch Files](https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/MobileHIG/LaunchImages.html). These are the same XIB files or Storyboards that you'd normally build you UI with in Xcode. This means you can use any iOS UI component and only need one file to support all devices. When you app first runs, iOS takes a snapshot image of the launch file to use as launch image. A great way to slim down your IPA!
16 |
17 | ## iPad Pro requires Launch Files
18 |
19 | The iPad Pro no longer supports Launch Images. Without it, a (Titanium) iOS app will be stretched to fit the iPad Pro:
20 |
21 | 
22 |
23 | The iPad Pro also requires a new 167px icon called `appicon-83.5@2x.png`. If you use [DefaultIcon[-ios].png](http://docs.appcelerator.com/platform/latest/#!/guide/Icons_and_Splash_Screens-section-29004897_IconsandSplashScreens-iOSgraphicassetrequirementsandoptions) it will be generated automatically since Titanium 5.1.2.GA.
24 |
25 | You can select the iPad Pro from the device list in Studio or use `-C ?` to select if from the CLI.
26 |
27 | ## Using Launch Files
28 |
29 | You have two ways to use Launch Files: by using our builtin Storyboard or your own.
30 |
31 | Both need to be enabled in the `` section of your [tiapp.xml](tiapp.xml#L28):
32 |
33 | true
34 |
35 | ## Option A: Use the builtin Storyboard
36 |
37 | The builtin Storyboard features a centered image on a solid background color. The sample uses the builtin storyboard with a [custom image](app/assets/iphone) on an [Appcelerator red Background Color](tiapp.xml#L31):
38 |
39 | 
40 |
41 | ### Customising the Image
42 |
43 | By default we'll generate the image from `DefaultIcon[-ios].png`. To use a different image, add the following `LaunchLogo*.png` files to the [app/assets/iphone](app/assets/iphone) folder:
44 |
45 | Filename | Devices | Scale | Recommended Size
46 | ---------|---------|-------|-----------------
47 | LaunchLogo~iphone.png | iPhone 3G and older | 1x | 320x320
48 | LaunchLogo@2x~iphone.png | iPhone 4, 4s 5, 5s, 6, 6s | 2x | 374x374
49 | LaunchLogo@3x~iphone.png | iPhone 6 Plus, 6s Plus | 3x | 621x621
50 | LaunchLogo~ipad.png | iPad 1, 2, Mini 1 | 1x | 384x384
51 | LaunchLogo@2x~ipad.png | iPad 3, 4, Air, Air 2, Mini 2, 3, 4 | 2x | 1024x1024
52 |
53 | You can generate these images with TiCons [Web](http://ticons.fokkezb.nl/) or [CLI](https://www.npmjs.com/package/ticons) `--storyboard` option.
54 |
55 | ### Customising the Background Color
56 |
57 | By default the background color is white. You can set a different color via the `` section of your [tiapp.xml](tiapp.xml#L31).
58 |
59 | This will also change the background color of your app between after the launch files is dismissed and before a view (with a solid background color) is opened, or [Ti.UI.backgroundColor](http://docs.appcelerator.com/platform/latest/#!/api/Titanium.UI-property-backgroundColor) is set. The sample [opens with a 2s delay](app/controllers/index.js#L23-L30) so you can see this better.
60 |
61 | ## Option B: Use a custom Storyboard
62 |
63 | To use a custom Storyboard, put this file in [platform/ios/LaunchScreen.storyboard](https://github.com/appcelerator/titanium_mobile/blob/master/iphone/iphone/LaunchScreen.storyboard). As you can see the sample has it disabled using a `_` prefix. Just remove the underscore and do a clean build to see the difference:
64 |
65 | 
66 |
67 | As you can see I've used an iOS Activity Indicator. Notice that it is not spinning as iOS uses a snapshot image of the storyboard.
68 |
69 | ### Using images
70 |
71 | To use an image in your custom Storyboard, simply set the `Image` property of an *Image View* to the path under `app/assets/` without the image modifier (`~ipad`, `@2x`) or extension:
72 |
73 | 
74 |
75 | > **NOTE:** [Currently](https://jira.appcelerator.org/browse/TIMOB-20429) Titanium does not package the `LaunchLogo*.png` file if you use a custom storyboard. You need to rename this image before you can use it.
76 |
77 | If you have the [optional app-thinning](http://docs.appcelerator.com/platform/latest/#!/guide/tiapp.xml_and_timodule.xml_Reference-section-29004921_tiapp.xmlandtimodule.xmlReference-use-app-thinning) enabled, you will have to use the name of the generated asset catalog. This is a hash based on the image path. To find out the hash for your image build the app, look up the right `[hash].imageset` under `build/iphone/Assets.xcassets/` and use the `[hash]` part.
78 |
79 | ## Dealing with Launch File Cache
80 |
81 | As you modify the (custom) storyboard, you might not always see your changes immediately. This is because iOS caches the snapshot it makes from your Launch File and a [known issue](https://jira.appcelerator.org/browse/TIMOB-20430) where Titanium does not always recompile the storyboard.
82 |
83 | To deal with this follow these steps before you build:
84 |
85 | 1. Use Simulator > Reset Content and Settings...
86 | 2. Use Project > Clean... or `appc ti clean` from CLI.
87 |
88 | Alternatively you can reset an individual app using a tool like [SimPholders](https://simpholders.com/). With this app, just hold `alt/⌥` and click the app from the dropdown:
89 |
90 | 
91 |
92 | ## Enabling Slide Over and Split View
93 |
94 | On to iPad multitasking.
95 |
96 | The reason this requires Launch Files is that your app might be opened as Slide Over in either landscape or portrait. This would have required a 6 more launch images for the 3 sizes of iPad screens out there.
97 |
98 | Because your app needs to deal with all these sizes as well, Auto Layout is required. So the first thing we need to do is enable this under the `` section of [tiapp.xml](tiapp.xml#L34):
99 |
100 | true
101 |
102 | To inform iOS that our app no longer requires fullscreen, we need to add a flag to the `` section of [tiapp.xml](tiapp.xml#L40-L41):
103 |
104 | UIRequiresFullScreen
105 |
106 |
107 | ## Responding to Slide Over and Split View
108 |
109 | Though Auto Layout should take care of resizing your UI properly, you might want to leave out certain views on smaller sizes.
110 |
111 | To respond to your app changing between full screen, Slide Over and quarter or half Split View you can listen to the existing [Ti.App:resumed](http://docs.appcelerator.com/platform/latest/#!/api/Titanium.App-event-resumed) event. This will fire on all occasions [except for one](https://jira.appcelerator.org/browse/TIMOB-20461). When your app is on the left side of a Split View and moves back to fullscreen because the other app closes or switches to Slide Over you will not get notified.
112 |
113 | In [index controller](app/controllers/index.js#L105) of the sample app I log the dimensions of the TabGroup each time the `resumed` event is received.
--------------------------------------------------------------------------------
/docs/livephotos.md:
--------------------------------------------------------------------------------
1 | # Titanium 5.2.0: iOS Live Photos
2 |
3 | [Titanium 5.2.0](http://www.appcelerator.com/blog/2016/02/ga-release-of-cli-5-2-titanium-5-2-and-studio-4-5/) has added support for [Live Photos](http://www.apple.com/iphone-6s/films/index.html#film-live-photos) that Apple [introduced with iOS 9.1](https://developer.apple.com/library/prerelease/ios/releasenotes/General/WhatsNewIniOS/Articles/iOS9_1.html) for the [iPhone 6s](http://www.apple.com/iphone-6s/cameras/). It allows you to select existing Live Photos and display them.
4 |
5 | In this blog post I'll walk you through all of this using the new [Titanium 5.2.0 Sample App](http://github.com/appcelerator-developer-relations/appc-sample-ti520):
6 |
7 | [](https://www.youtube.com/watch?v=XAxrq1hq7JA)
8 |
9 | ## Capturing a Live Photo
10 | Although Apple's [Reference](https://developer.apple.com/library/prerelease/ios/documentation/UIKit/Reference/UIImagePickerController_Class/index.html#//apple_ref/doc/uid/TP40007070-CH3-DontLinkElementID_2) isn't really clear about it does say:
11 |
12 | > Live Photos is a Camera app feature on supported devices ...
13 |
14 | And that has indeed been our experience and that of app developers that work directly in Objective-C or Swift. Even when we do include the Live Photo media type, the UI for taking a new photo within another app will not include the *Live* icon and does not return a Live Photo. We will provide support soon after Apple does.
15 |
16 | ## Selecting a Live Photo
17 | To select a Live Photo from your device you use [Ti.Media.openPhotoGallery()](http://docs.appcelerator.com/platform/latest/#!/api/Titanium.Media-method-openPhotoGallery) as always. Live Photos will always be selectable, but only if you include `Ti.Media.MEDIA_TYPE_LIVEPHOTO` in the [mediaTypes](http://docs.appcelerator.com/platform/latest/#!/api/PhotoGalleryOptionsType-property-mediaTypes) will you get an actual [livePhoto](http://docs.appcelerator.com/platform/latest/#!/api/CameraMediaItemType-property-livePhoto) in the success response. Both ways, the existing [media](http://docs.appcelerator.com/platform/latest/#!/api/CameraMediaItemType-property-media) property will always get you the plain photo.
18 |
19 | > **NOTE:** You cannot use `Ti.Media.MEDIA_TYPE_LIVEPHOTO` without also including `Ti.Media.MEDIA_TYPE_PHOTO` in `mediaTypes`.
20 |
21 | See the the Sample App's [livephoto.js](../app/controllers/ios/livephoto.js) controller for the implementation.
22 |
23 | ## Displaying a Live Photo
24 | Live Photos cannot be displayed in a `Ti.UI.ImageView`, but only the new [Ti.UI.iOS.LivePhotoView](http://docs.appcelerator.com/platform/latest/#!/api/Titanium.UI.iOS.LivePhotoView).
25 |
26 | Alloy [does not yet support LivePhotoView](https://jira.appcelerator.org/browse/ALOY-1356) which means we have to tell Alloy to use the `Ti.UI.iOS` namespace [ourselves](../app/views/ios/livephoto.xml#L10-L11):
27 |
28 |
29 |
30 | Set the view's [livePhoto](http://docs.appcelerator.com/platform/latest/#!/api/Titanium.UI.iOS.LivePhotoView-property-livePhoto) property to the [Ti.UI.iOS.LivePhoto](http://docs.appcelerator.com/platform/latest/#!/api/Titanium.UI.iOS.LivePhoto) proxy that you received from `Ti.Media.openPhotoGallery()`.
31 |
32 | The view supports force touch interaction with the Live Photo out of the box. Just force touch the view to play the Live Photo.
33 |
34 | ## Programmatic Playback
35 | You can also programmatically start and stop the playback. Use [Ti.UI.iOS.LivePhotoView.startPlaybackWithStyle()](http://docs.appcelerator.com/platform/latest/#!/api/Titanium.UI.iOS.LivePhotoView-method-startPlaybackWithStyle) to start and [stopPlayback()](http://docs.appcelerator.com/platform/latest/#!/api/Titanium.UI.iOS.LivePhotoView-method-stopPlayback) to cancel. The first method accepts a [parameter](http://docs.appcelerator.com/platform/latest/#!/api/Titanium.UI.iOS.LivePhotoView-method-stopPlayback) to select full playback or the hint style that you also see as a LivePhoto scrolls into view in the Photos app. This is also the only use case that Apple suggests you should use this method for.
36 |
37 | In the [livephoto.js](../app/controllers/ios/livephoto.js#L34) controller we playback with hint style after we've initialised the LivePhotoView with the Live Photo you selected:
38 |
39 | $.livePhotoView.startPlaybackWithStyle(Ti.UI.iOS.LIVEPHOTO_PLAYBACK_STYLE_HINT);
40 |
41 | # Events
42 | In addition to regular events, the view also features a [start](http://docs.appcelerator.com/platform/latest/#!/api/Titanium.UI.iOS.LivePhotoView-event-start) and [stop](http://docs.appcelerator.com/platform/latest/#!/api/Titanium.UI.iOS.LivePhotoView-event-stop) event to inform you when the Live Photo has plays.
43 |
--------------------------------------------------------------------------------
/docs/streetview.md:
--------------------------------------------------------------------------------
1 | # Titanium 5.2.0: Google Street View Panorama
2 |
3 | The [ti.map 2.3.6](https://github.com/appcelerator-modules/ti.map) module that comes with [Titanium 5.2.0](http://www.appcelerator.com/blog/2016/02/ga-release-of-cli-5-2-titanium-5-2-and-studio-4-5/) adds support for [Google StreetViewPanorama](https://developers.google.com/maps/documentation/android-api/streetview). This allows you to integrate Street View in your Titanium Android apps.
4 |
5 | In this blog post I'll walk you through all of this using the new [Titanium 5.2.0 Sample App](http://github.com/appcelerator-developer-relations/appc-sample-ti520):
6 |
7 | 
8 |
9 | *Yes, that's our [San Jose HQ](https://goo.gl/maps/1bAiuvwBoQ42) you're looking at!*
10 |
11 | ## Add the Maps Module
12 |
13 | Since the module is bundled with the Titanium SDK you don't need to download it. You do need to add it to your [tiapp.xml](tiapp.xml#L112-L113):
14 |
15 |
16 | ti.map
17 |
18 |
19 | In Studio you can use the TiApp Editor:
20 |
21 | 
22 |
23 | ## Initialize the Maps Module
24 |
25 | Google requires you to [request an API key](http://docs.appcelerator.com/platform/latest/#!/guide/Google_Maps_v2_for_Android-section-36739898_GoogleMapsv2forAndroid-ObtainandAddaGoogleAPIKey) that is linked to your App ID and the keystore you use when you build the app. You need to then add this API key to your `tiapp.xml` as well:
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 | The Sample App has an [API key configured](../tiapp.xml#L101) that is valid for its App ID and our [builtin development keystore](https://github.com/appcelerator/titanium_mobile/blob/master/support/android/dev_keystore).
36 |
37 | ## Add the StreetViewPanorama
38 |
39 | To add the new StreetViewPanorama we have used Alloy's `module` attribute in the [streetview.xml](../app/views/android/streetview.xml#L6) view:
40 |
41 |
42 |
43 | You should know that Alloy normally transpiles `` elements to `Ti.UI.createFoo()`. You can use the `ns` attribute to let Alloy using something else then `Ti.UI`, which is what we needed for [Live Photos](livephotos.md). The `module` attribute is very similar but its value will be wrapped in `require(..)`. This means we can load any native or CommonJS module to deliver us the view factory method(s) we need.
44 |
45 | ## Configure the StreetViewPanorama
46 |
47 | The [API reference](http://docs.appcelerator.com/platform/latest/#!/api/Modules.Map) for the StreetViewPanorama is currently [missing](https://jira.appcelerator.org/browse/TIDOC-2450). Luckily there's just a few properties and the samples shows you all of them.
48 |
49 | ### Set the location
50 | First of all we need to set the position. We use the ID we've assigned the tag in the above XML view to set the position in [streetview.tss](../app/styles/android/streetview.tss#L1-L8):
51 |
52 | '#streetView': {
53 | position: {
54 | latitude: 37.3676332,
55 | longitude: -121.9139205
56 | }
57 | }
58 |
59 | > **NOTE:** Strange enough the [Android API](https://developers.google.com/maps/documentation/android-api/streetview#set_the_location_of_the_panorama) does not allow you set the heading. It seems always start headed North.
60 |
61 | ### Customize the user-controlled functionality
62 | There are a few features you can disable. All of them are on by default. In the Sample App I have [overlaid some buttons](../app/views/android/streetview.xml#L8-L13) so you can easily [toggle](../app/controllers/android/streetview.js#L5-L13) these boolean properties.
63 |
64 | * `panning`: Determines whether the user will be able to re-orient the camera by dragging.
65 | * `userNavigation`: Determines whether the user will be able to move to a different panorama. Users can use a single tap on navigation links, or double tap the view, to move to a new panorama.
66 | * `zoom`: Determines whether the user will be able to pinch to zoom.
67 | * `streetNames`: Determines whether the user is able to see street names displayed on the ground.
68 |
69 | ## Run on Android Device or Emulator
70 |
71 | To use Google Maps the device or emulator needs to have [Google Play Services](https://developers.google.com/android/guides/overview) installed. This comes - and is silently updated - with the Google Play app that you will find on pretty much any Android device.
72 |
73 | Unfortunately, the popular [Genymotion](https://www.genymotion.com/) emulator [comes without Google Apps](https://www.genymotion.com/faq/#google-apps-missing) because of a legal dispute with Google. You can find instructions on how to add Google Apps to Genymotion emulators on [Google](https://www.google.com/search?q=genymotion%20google%20apps).
74 |
75 | However, you might also consider giving the stock AVDs (Android Virtual Device) another try. Most of them include Google APIs, the performance has improved a lot recently and [Android Studio](http://developer.android.com/sdk/index.html) makes it very easy to [manage AVDs](http://developer.android.com/tools/devices/managing-avds.html) for tons of common devices:
76 |
77 | 
78 |
79 | And yes, these AVDs work fine with Titanium!
80 |
81 | Code Strong! 🚀
82 |
--------------------------------------------------------------------------------
/docs/transitions.md:
--------------------------------------------------------------------------------
1 | # Titanium 5.2.0: Android Activity & Shared Element Transitions
2 |
3 | Android 5.0 (API level 21) introduced [Material Design](http://developer.android.com/design/material/index.html): a vision, [design guidelines](http://www.google.com/design/spec/material-design/introduction.html) as well as new components and animations. Earlier in Titanium 5.1.0 we added support for [CardView](https://github.com/appcelerator-developer-relations/appc-sample-ti510#cardview), the [Reveal Effect](https://github.com/appcelerator-developer-relations/appc-sample-ti510#reveal-effect) animation as additional support for the [material design theme](https://github.com/appcelerator-developer-relations/appc-sample-ti510#progressbar-color).
4 |
5 | Now in [Titanium 5.2.0](http://www.appcelerator.com/blog/2016/02/ga-release-of-cli-5-2-titanium-5-2-and-studio-4-5/) we add support for customized [Activity & Shared Element Transitions](https://developer.android.com/training/material/animations.html#Transitions). In this blog post I'll walk you through this using the new [Titanium 5.2.0 Sample App](http://github.com/appcelerator-developer-relations/appc-sample-ti520):
6 |
7 | [](https://www.youtube.com/watch?v=Cg8HmQBP4jk)
8 |
9 | ## What is an Activity?
10 | In Titanium each Window or TabGroup creates and is linked to a new [Activity](http://developer.android.com/guide/components/activities.html). When the user presses the [system back button](http://developer.android.com/training/implementing-navigation/temporal.html) he will return to the previous activity on the stack. You can access the Activity via the [activity property](http://docs.appcelerator.com/platform/latest/#!/api/Titanium.UI.Window-property-activity).
11 |
12 | ## What Activity Transitions are there?
13 |
14 | It's important to understand the difference between the different transitions an activity goes through that you can customize. You can see all four of them explained in the following diagram:
15 |
16 | 
17 |
18 | As you go from Window A to B, Window A will **exit** and B will **enter**. When you press the system back button to return to Window A, then Window B will **return** and A will **reenter**.
19 |
20 | > **NOTE:** It's a known issue that when you programmatically close a Window using its `close()` the **return** and **reenter** transitions are ignored ([TIMOB-20451](https://jira.appcelerator.org/browse/TIMOB-20451)). The system back button shows the expected behaviour.
21 |
22 | For more details I recommend Alex Lockwood's [Getting Started with Activity & Fragment Transitions](http://www.androiddesignpatterns.com/2014/12/activity-fragment-transitions-in-android-lollipop-part1.html).
23 |
24 | ## How to customize Activity Transitions?
25 |
26 | First of all, the Android APIs are designed in such a way that as soon as you define shared elements, both the `activity*Transition`s and `sharedElement*Transition`s get defaults (which I'll get to soon) that you're unlikely to need to change at all.
27 |
28 | > **NOTE:** Currently Activity Transitions will only work if you have declared shared elements. We're looking into making them work without as well ([TIMOB-20507](https://jira.appcelerator.org/browse/TIMOB-20507)).
29 |
30 | To customize the transitions you can use the following properties:
31 |
32 | * `Ti.UI.Window.activityExitTransition`
33 | * `Ti.UI.Window.activityEnterTransition`
34 | * `Ti.UI.Window.activityReturnTransition`
35 | * `Ti.UI.Window.activityReenterTransition`
36 |
37 | > **NOTE:** Unfortunately the API reference of these properties currently has them located under the Window `open()` and `close()` [parameters](http://docs.appcelerator.com/platform/latest/#!/api/openWindowParams) ([TIDOC-2454](https://jira.appcelerator.org/browse/TIDOC-2454)).
38 |
39 | The above properties can be set to the following constants:
40 |
41 | * [`Ti.UI.Android.TRANSITION_EXPLODE`](http://docs.appcelerator.com/platform/latest/#!/api/Titanium.UI.Android-property-TRANSITION_EXPLODE)
42 | * [`Ti.UI.Android.TRANSITION_FADE_IN`](http://docs.appcelerator.com/platform/latest/#!/api/Titanium.UI.Android-property-TRANSITION_FADE_IN)
43 | * [`Ti.UI.Android.TRANSITION_FADE_OUT`](http://docs.appcelerator.com/platform/latest/#!/api/Titanium.UI.Android-property-TRANSITION_FADE_OUT)
44 | * [`Ti.UI.Android.TRANSITION_SLIDE_TOP`](http://docs.appcelerator.com/platform/latest/#!/api/Titanium.UI.Android-property-TRANSITION_SLIDE_TOP)
45 | * [`Ti.UI.Android.TRANSITION_SLIDE_RIGHT`](http://docs.appcelerator.com/platform/latest/#!/api/Titanium.UI.Android-property-SLIDE_RIGHT)
46 | * [`Ti.UI.Android.TRANSITION_SLIDE_BOTTOM`](http://docs.appcelerator.com/platform/latest/#!/api/Titanium.UI.Android-property-SLIDE_BOTTOM)
47 | * [`Ti.UI.Android.TRANSITION_SLIDE_LEFT`](http://docs.appcelerator.com/platform/latest/#!/api/Titanium.UI.Android-property-SLIDE_LEFT)
48 | * [`Ti.UI.Android.TRANSITION_NONE`](http://docs.appcelerator.com/platform/latest/#!/api/Titanium.UI.Android-property-TRANSITION_NONE)
49 |
50 | The sample lets you [set these properties](../app/views/android/transitions_a.xml#L8) from within the app to play with the options.
51 |
52 | ### Transition defaults
53 | In most cases you will only set **enter** and **exit** because **reenter** will default to **exit** as will **return** to **enter**. In turn, **exit** defaults to no animation and **enter** to `FADE_INT`.
54 |
55 | ### Disable transitions
56 | You can disable transitions at all time by passing `{animated:false}` to the Window `open()` or `close()` method. As mentioned, they will currently also not be used if you don't declare any shared elements.
57 |
58 | ## What Shared Element Transitions are there?
59 | Again, Alex Lockwood does a great job at explaining working with [Shared Elements](http://www.androiddesignpatterns.com/2015/01/activity-fragment-shared-element-transitions-in-depth-part3a.html).
60 |
61 | What it comes down to is that as you transition from one Window to the next you can link individual related views between both Windows and have them animate from one to the other as if they were one.
62 |
63 | If you scroll back to the screenrecording of our Sample App you can see that the Appcelerator logo and the next underneath display this behaviour. Again, the sample allows you to change the transition style for these shared elements.
64 |
65 | ## How to customize Shared Element Transitions?
66 |
67 | Like I said the Android APIs are designed in such a way that you're unlikely to want to change the defaults. But as with Activity Transitions, we have four properties we can use to do so anyway. Their names might be very similar to those for the Activity Transitions, but their meaning is slightly different.
68 |
69 | > **NOTE:** Unfortunately the API reference of these properties currently has them located under the Window `open()` and `close()` [parameters](http://docs.appcelerator.com/platform/latest/#!/api/openWindowParams) ([TIDOC-2454](https://jira.appcelerator.org/browse/TIDOC-2454)).
70 |
71 | Let's start with two properties you can set on Window B:
72 |
73 | * `Ti.UI.Window.activitySharedElementEnterTransition` to determine how shared elements animate from A to B. Defaults to all of them in parallel.
74 | * `Ti.UI.Window.activitySharedElementReturnTransition` to determine how shared elements animate form B to A. Defaults to all of them in parallel.
75 |
76 | Additionally you can also set two properties on Window A. Now as Alex [points out](http://www.androiddesignpatterns.com/2015/01/activity-fragment-shared-element-transitions-in-depth-part3a.html#footnote1) there are very use cases for these two. In fact, the animations Titanium currently exposes would not be noticeable.
77 |
78 | * `Ti.UI.Window.activitySharedElementExitTransition` animates shared elements **before** they use B's **enter** transition to animate from A to B.
79 | * `Ti.UI.Window.activitySharedElementReeenterTransition` animated shared elements **after** they use B's **return** transition to animate from B to A. Defaults to the **exit** transition.
80 |
81 | You can set these four properties to the following constants:
82 |
83 | * [`Ti.UI.Android.TRANSITION_CHANGE_BOUNDS`](http://docs.appcelerator.com/platform/latest/#!/api/Titanium.UI.Android-property-TRANSITION_CHANGE_BOUNDS)
84 | * [`Ti.UI.Android.TRANSITION_CHANGE_CLIP_BOUNDS`](http://docs.appcelerator.com/platform/latest/#!/api/Titanium.UI.Android-property-TRANSITION_CLIP_BOUNDS)
85 | * [`Ti.UI.Android.TRANSITION_CHANGE_TRANSFORM`](http://docs.appcelerator.com/platform/latest/#!/api/Titanium.UI.Android-property-TRANSITION_CHANGE_TRANSFORM)
86 | * [`Ti.UI.Android.TRANSITION_CHANGE_IMAGE_TRANSFORM`](http://docs.appcelerator.com/platform/latest/#!/api/Titanium.UI.Android-property-TRANSITION_CHANGE_IMAGE_TRANSFORM)
87 | * [`Ti.UI.Android.TRANSITION_NONE`](http://docs.appcelerator.com/platform/latest/#!/api/Titanium.UI.Android-property-TRANSITION_NONE)
88 |
89 | ## How to define Shared Elements to enable these Transitions?
90 |
91 | Now how do we put all these properties and constants into use and actually define Shared Elements so that we can see both the Activity and Shared Element Transitions in action?
92 |
93 | 1. In both Windows we need to set the new [transitionName](http://docs.appcelerator.com/platform/latest/#!/api/Titanium.UI.View-property-transitionName) property to the same value for each shared element. You can see we've done this in [Window A](../app/views/android/transitions_a.xml#L66-L67) and [Window B](../app/views/android/transitions_b.xml#L7-L9) of our Sample App. The name should be unique within each Window.
94 | 2. Before we open Window B we then need to use its new [addSharedElement()](http://docs.appcelerator.com/platform/latest/#!/api/Titanium.UI.Window-method-addSharedElement) method. This method takes two properties. The first should be a reference to the shared view in Window A. The second is the value of `transitionName` as it can be found in Window B.
95 |
96 | Sounds confusing?
97 |
98 | Have a look at the Sample's [transitions_a.xml](../app/views/android/transitions_a.xml#L66-L67), [transitions_b.xml](../app/views/android/transitions_b.xml#L7-L9) and [transition_a.js](../app/controllers/android/transitions_a.js#L30-L31). In the end, when you rely on the default transition animations, this is all you need to set.
99 |
100 | In both views:
101 |
102 | ```
103 |
104 |
105 | ```
106 |
107 | In the controller for Window A, before opening Window B:
108 |
109 | ```
110 | win.addSharedElement($.logo, 'logo');
111 | win.addSharedElement($.text, 'text');
112 | ```
113 |
114 | Let's make some truly *animating* Titanium Android apps!
115 |
116 | \- Code Strong 🚀
117 |
--------------------------------------------------------------------------------
/extensions/Ti 5.2.0/Ti 5.2.0 WatchKit App/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "24x24",
5 | "idiom" : "watch",
6 | "filename" : "icon-24@2x.png",
7 | "scale" : "2x",
8 | "role" : "notificationCenter",
9 | "subtype" : "38mm"
10 | },
11 | {
12 | "size" : "27.5x27.5",
13 | "idiom" : "watch",
14 | "filename" : "icon-27.5@2x.png",
15 | "scale" : "2x",
16 | "role" : "notificationCenter",
17 | "subtype" : "42mm"
18 | },
19 | {
20 | "size" : "29x29",
21 | "idiom" : "watch",
22 | "filename" : "icon-29@2x.png",
23 | "role" : "companionSettings",
24 | "scale" : "2x"
25 | },
26 | {
27 | "size" : "29x29",
28 | "idiom" : "watch",
29 | "filename" : "icon-29@3x.png",
30 | "role" : "companionSettings",
31 | "scale" : "3x"
32 | },
33 | {
34 | "size" : "40x40",
35 | "idiom" : "watch",
36 | "filename" : "icon-40@2x.png",
37 | "scale" : "2x",
38 | "role" : "appLauncher",
39 | "subtype" : "38mm"
40 | },
41 | {
42 | "size" : "44x44",
43 | "idiom" : "watch",
44 | "filename" : "icon-44@2x.png",
45 | "scale" : "2x",
46 | "role" : "longLook",
47 | "subtype" : "42mm"
48 | },
49 | {
50 | "size" : "86x86",
51 | "idiom" : "watch",
52 | "filename" : "icon-86@2x.png",
53 | "scale" : "2x",
54 | "role" : "quickLook",
55 | "subtype" : "38mm"
56 | },
57 | {
58 | "size" : "98x98",
59 | "idiom" : "watch",
60 | "filename" : "icon-98@2x.png",
61 | "scale" : "2x",
62 | "role" : "quickLook",
63 | "subtype" : "42mm"
64 | }
65 | ],
66 | "info" : {
67 | "version" : 1,
68 | "author" : "xcode"
69 | }
70 | }
--------------------------------------------------------------------------------
/extensions/Ti 5.2.0/Ti 5.2.0 WatchKit App/Assets.xcassets/AppIcon.appiconset/icon-24@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appcelerator-developer-relations/appc-sample-ti520/e91e8b14182114b2912d60cd4604dc06170df8e7/extensions/Ti 5.2.0/Ti 5.2.0 WatchKit App/Assets.xcassets/AppIcon.appiconset/icon-24@2x.png
--------------------------------------------------------------------------------
/extensions/Ti 5.2.0/Ti 5.2.0 WatchKit App/Assets.xcassets/AppIcon.appiconset/icon-27.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appcelerator-developer-relations/appc-sample-ti520/e91e8b14182114b2912d60cd4604dc06170df8e7/extensions/Ti 5.2.0/Ti 5.2.0 WatchKit App/Assets.xcassets/AppIcon.appiconset/icon-27.5@2x.png
--------------------------------------------------------------------------------
/extensions/Ti 5.2.0/Ti 5.2.0 WatchKit App/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appcelerator-developer-relations/appc-sample-ti520/e91e8b14182114b2912d60cd4604dc06170df8e7/extensions/Ti 5.2.0/Ti 5.2.0 WatchKit App/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png
--------------------------------------------------------------------------------
/extensions/Ti 5.2.0/Ti 5.2.0 WatchKit App/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appcelerator-developer-relations/appc-sample-ti520/e91e8b14182114b2912d60cd4604dc06170df8e7/extensions/Ti 5.2.0/Ti 5.2.0 WatchKit App/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png
--------------------------------------------------------------------------------
/extensions/Ti 5.2.0/Ti 5.2.0 WatchKit App/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appcelerator-developer-relations/appc-sample-ti520/e91e8b14182114b2912d60cd4604dc06170df8e7/extensions/Ti 5.2.0/Ti 5.2.0 WatchKit App/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png
--------------------------------------------------------------------------------
/extensions/Ti 5.2.0/Ti 5.2.0 WatchKit App/Assets.xcassets/AppIcon.appiconset/icon-44@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appcelerator-developer-relations/appc-sample-ti520/e91e8b14182114b2912d60cd4604dc06170df8e7/extensions/Ti 5.2.0/Ti 5.2.0 WatchKit App/Assets.xcassets/AppIcon.appiconset/icon-44@2x.png
--------------------------------------------------------------------------------
/extensions/Ti 5.2.0/Ti 5.2.0 WatchKit App/Assets.xcassets/AppIcon.appiconset/icon-86@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appcelerator-developer-relations/appc-sample-ti520/e91e8b14182114b2912d60cd4604dc06170df8e7/extensions/Ti 5.2.0/Ti 5.2.0 WatchKit App/Assets.xcassets/AppIcon.appiconset/icon-86@2x.png
--------------------------------------------------------------------------------
/extensions/Ti 5.2.0/Ti 5.2.0 WatchKit App/Assets.xcassets/AppIcon.appiconset/icon-98@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appcelerator-developer-relations/appc-sample-ti520/e91e8b14182114b2912d60cd4604dc06170df8e7/extensions/Ti 5.2.0/Ti 5.2.0 WatchKit App/Assets.xcassets/AppIcon.appiconset/icon-98@2x.png
--------------------------------------------------------------------------------
/extensions/Ti 5.2.0/Ti 5.2.0 WatchKit App/Base.lproj/Interface.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/extensions/Ti 5.2.0/Ti 5.2.0 WatchKit App/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | Ti 5.2.0
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 1
25 | UISupportedInterfaceOrientations
26 |
27 | UIInterfaceOrientationPortrait
28 | UIInterfaceOrientationPortraitUpsideDown
29 |
30 | WKCompanionAppBundleIdentifier
31 | com.appcelerator.sample.ti520
32 | WKWatchKitApp
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/extensions/Ti 5.2.0/Ti 5.2.0 WatchKit Extension/Assets.xcassets/README__ignoredByTemplate__:
--------------------------------------------------------------------------------
1 | Did you know that git does not support storing empty directories?
2 |
--------------------------------------------------------------------------------
/extensions/Ti 5.2.0/Ti 5.2.0 WatchKit Extension/ExtensionDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // ExtensionDelegate.h
3 | // Ti 5.2.0 WatchKit Extension
4 | //
5 | // Created by Appcelerator on 2/18/2016.
6 | // 2016 by Appcelerator, Inc. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface ExtensionDelegate : NSObject
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/extensions/Ti 5.2.0/Ti 5.2.0 WatchKit Extension/ExtensionDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // ExtensionDelegate.m
3 | // Ti 5.2.0 WatchKit Extension
4 | //
5 | // Created by Appcelerator on 2/18/2016.
6 | // 2016 by Appcelerator, Inc. All rights reserved.
7 | //
8 |
9 | #import "ExtensionDelegate.h"
10 |
11 | @implementation ExtensionDelegate
12 |
13 | - (void)applicationDidFinishLaunching {
14 | // Perform any final initialization of your application.
15 | }
16 |
17 | - (void)applicationDidBecomeActive {
18 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
19 | }
20 |
21 | - (void)applicationWillResignActive {
22 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
23 | // Use this method to pause ongoing tasks, disable timers, etc.
24 | }
25 |
26 | @end
27 |
--------------------------------------------------------------------------------
/extensions/Ti 5.2.0/Ti 5.2.0 WatchKit Extension/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | Ti 5.2.0
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | XPC!
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 1
25 | NSExtension
26 |
27 | NSExtensionAttributes
28 |
29 | WKAppBundleIdentifier
30 | com.appcelerator.sample.ti520.watchkitapp
31 |
32 | NSExtensionPointIdentifier
33 | com.apple.watchkit
34 |
35 | RemoteInterfacePrincipalClass
36 | $(PRODUCT_MODULE_NAME).InterfaceController
37 | WKExtensionDelegateClassName
38 | $(PRODUCT_MODULE_NAME).ExtensionDelegate
39 |
40 |
41 |
--------------------------------------------------------------------------------
/extensions/Ti 5.2.0/Ti 5.2.0 WatchKit Extension/InterfaceController.h:
--------------------------------------------------------------------------------
1 | //
2 | // InterfaceController.h
3 | // Ti 5.2.0 WatchKit Extension
4 | //
5 | // Created by Appcelerator on 2/18/2016.
6 | // 2016 by Appcelerator, Inc. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 | #import
12 |
13 | @interface InterfaceController : WKInterfaceController
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/extensions/Ti 5.2.0/Ti 5.2.0 WatchKit Extension/InterfaceController.m:
--------------------------------------------------------------------------------
1 | //
2 | // InterfaceController.m
3 | // Ti 5.2.0 WatchKit Extension
4 | //
5 | // Created by Appcelerator on 2/18/2016.
6 | // 2016 by Appcelerator, Inc. All rights reserved.
7 | //
8 |
9 | #import "InterfaceController.h"
10 |
11 |
12 | @interface InterfaceController()
13 |
14 | @end
15 |
16 |
17 | @implementation InterfaceController
18 |
19 | - (instancetype)init {
20 | self = [super init];
21 |
22 | if (self) {
23 |
24 | if ([WCSession isSupported]) {
25 | WCSession* session = [WCSession defaultSession];
26 | session.delegate = self;
27 | [session activateSession];
28 | }
29 | }
30 |
31 | return self;
32 | }
33 |
34 | - (void)awakeWithContext:(id)context {
35 | [super awakeWithContext:context];
36 |
37 | // Configure interface objects here.
38 | }
39 |
40 | - (void)willActivate {
41 | // This method is called when watch view controller is about to be visible to user
42 | [super willActivate];
43 | }
44 |
45 | - (void)didDeactivate {
46 | // This method is called when watch view controller is no longer visible
47 | [super didDeactivate];
48 | }
49 |
50 | @end
51 |
--------------------------------------------------------------------------------
/extensions/Ti 5.2.0/Ti 5.2.0 WatchKit Extension/NotificationController.h:
--------------------------------------------------------------------------------
1 | //
2 | // NotificationController.h
3 | // Ti 5.2.0 WatchKit Extension
4 | //
5 | // Created by Appcelerator on 2/18/2016.
6 | // 2016 by Appcelerator, Inc. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 |
12 | @interface NotificationController : WKUserNotificationInterfaceController
13 |
14 | @end
15 |
--------------------------------------------------------------------------------
/extensions/Ti 5.2.0/Ti 5.2.0 WatchKit Extension/NotificationController.m:
--------------------------------------------------------------------------------
1 | //
2 | // NotificationController.m
3 | // Ti 5.2.0 WatchKit Extension
4 | //
5 | // Created by Appcelerator on 2/18/2016.
6 | // 2016 by Appcelerator, Inc. All rights reserved.
7 | //
8 |
9 | #import "NotificationController.h"
10 |
11 |
12 | @interface NotificationController()
13 |
14 | @end
15 |
16 |
17 | @implementation NotificationController
18 |
19 | - (instancetype)init {
20 | self = [super init];
21 | if (self){
22 | // Initialize variables here.
23 | // Configure interface objects here.
24 |
25 | }
26 | return self;
27 | }
28 |
29 | - (void)willActivate {
30 | // This method is called when watch view controller is about to be visible to user
31 | [super willActivate];
32 | }
33 |
34 | - (void)didDeactivate {
35 | // This method is called when watch view controller is no longer visible
36 | [super didDeactivate];
37 | }
38 |
39 | /*
40 | - (void)didReceiveLocalNotification:(UILocalNotification *)localNotification withCompletion:(void (^)(WKUserNotificationInterfaceType))completionHandler {
41 | // This method is called when a local notification needs to be presented.
42 | // Implement it if you use a dynamic notification interface.
43 | // Populate your dynamic notification interface as quickly as possible.
44 | //
45 | // After populating your dynamic notification interface call the completion block.
46 | completionHandler(WKUserNotificationInterfaceTypeCustom);
47 | }
48 | */
49 |
50 | /*
51 | - (void)didReceiveRemoteNotification:(NSDictionary *)remoteNotification withCompletion:(void (^)(WKUserNotificationInterfaceType))completionHandler {
52 | // This method is called when a remote notification needs to be presented.
53 | // Implement it if you use a dynamic notification interface.
54 | // Populate your dynamic notification interface as quickly as possible.
55 | //
56 | // After populating your dynamic notification interface call the completion block.
57 | completionHandler(WKUserNotificationInterfaceTypeCustom);
58 | }
59 | */
60 |
61 | @end
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/extensions/Ti 5.2.0/Ti 5.2.0 WatchKit Extension/PushNotificationPayload.apns:
--------------------------------------------------------------------------------
1 | {
2 | "aps": {
3 | "alert": {
4 | "body": "Test message",
5 | "title": "Optional title"
6 | },
7 | "category": "myCategory"
8 | },
9 |
10 | "WatchKit Simulator Actions": [
11 | {
12 | "title": "First Button",
13 | "identifier": "firstButtonAction"
14 | }
15 | ],
16 |
17 | "customKey": "Use this file to define a testing payload for your notifications. The aps dictionary specifies the category, alert text and title. The WatchKit Simulator Actions array can provide info for one or more action buttons in addition to the standard Dismiss button. Any other top level keys are custom payload. If you have multiple such JSON files in your project, you'll be able to select them when choosing to debug the notification interface of your Watch App."
18 | }
19 |
--------------------------------------------------------------------------------
/extensions/Ti 5.2.0/Ti 5.2.0.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 83BEF1CF1B5453F4006F38C4 /* Interface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 83BEF1CD1B5453F4006F38C4 /* Interface.storyboard */; };
11 | 83BEF1D11B5453F4006F38C4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 83BEF1D01B5453F4006F38C4 /* Assets.xcassets */; };
12 | 83BEF1D81B5453F4006F38C4 /* Ti 5.2.0 WatchKit Extension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 83BEF1D71B5453F4006F38C4 /* Ti 5.2.0 WatchKit Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
13 | 83BEF1E01B5453F4006F38C4 /* InterfaceController.m in Sources */ = {isa = PBXBuildFile; fileRef = 83BEF1DF1B5453F4006F38C4 /* InterfaceController.m */; };
14 | 83BEF1E31B5453F4006F38C4 /* ExtensionDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 83BEF1E21B5453F4006F38C4 /* ExtensionDelegate.m */; };
15 | 83BEF1E61B5453F4006F38C4 /* NotificationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 83BEF1E51B5453F4006F38C4 /* NotificationController.m */; };
16 | 83BEF1EB1B5453F4006F38C4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 83BEF1EA1B5453F4006F38C4 /* Assets.xcassets */; };
17 | /* End PBXBuildFile section */
18 |
19 | /* Begin PBXContainerItemProxy section */
20 | 83BEF1D91B5453F4006F38C4 /* PBXContainerItemProxy */ = {
21 | isa = PBXContainerItemProxy;
22 | containerPortal = 83BEF18B1B5453D8006F38C4 /* Project object */;
23 | proxyType = 1;
24 | remoteGlobalIDString = 83BEF1D61B5453F4006F38C4;
25 | remoteInfo = "Ti 5.2.0 WatchKit Extension";
26 | };
27 | /* End PBXContainerItemProxy section */
28 |
29 | /* Begin PBXCopyFilesBuildPhase section */
30 | 83BEF1F31B5453F4006F38C4 /* Embed App Extensions */ = {
31 | isa = PBXCopyFilesBuildPhase;
32 | buildActionMask = 2147483647;
33 | dstPath = "";
34 | dstSubfolderSpec = 13;
35 | files = (
36 | 83BEF1D81B5453F4006F38C4 /* Ti 5.2.0 WatchKit Extension.appex in Embed App Extensions */,
37 | );
38 | name = "Embed App Extensions";
39 | runOnlyForDeploymentPostprocessing = 0;
40 | };
41 | /* End PBXCopyFilesBuildPhase section */
42 |
43 | /* Begin PBXFileReference section */
44 | 83BEF1CB1B5453F4006F38C4 /* Ti 5.2.0 WatchKit App.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Ti 5.2.0 WatchKit App.app"; sourceTree = BUILT_PRODUCTS_DIR; };
45 | 83BEF1CE1B5453F4006F38C4 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Interface.storyboard; sourceTree = ""; };
46 | 83BEF1D01B5453F4006F38C4 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
47 | 83BEF1D21B5453F4006F38C4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
48 | 83BEF1D71B5453F4006F38C4 /* Ti 5.2.0 WatchKit Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "Ti 5.2.0 WatchKit Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; };
49 | 83BEF1DD1B5453F4006F38C4 /* PushNotificationPayload.apns */ = {isa = PBXFileReference; lastKnownFileType = text; path = PushNotificationPayload.apns; sourceTree = ""; };
50 | 83BEF1DE1B5453F4006F38C4 /* InterfaceController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = InterfaceController.h; sourceTree = ""; };
51 | 83BEF1DF1B5453F4006F38C4 /* InterfaceController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = InterfaceController.m; sourceTree = ""; };
52 | 83BEF1E11B5453F4006F38C4 /* ExtensionDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ExtensionDelegate.h; sourceTree = ""; };
53 | 83BEF1E21B5453F4006F38C4 /* ExtensionDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ExtensionDelegate.m; sourceTree = ""; };
54 | 83BEF1E41B5453F4006F38C4 /* NotificationController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NotificationController.h; sourceTree = ""; };
55 | 83BEF1E51B5453F4006F38C4 /* NotificationController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NotificationController.m; sourceTree = ""; };
56 | 83BEF1EA1B5453F4006F38C4 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
57 | 83BEF1EC1B5453F4006F38C4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
58 | /* End PBXFileReference section */
59 |
60 | /* Begin PBXFrameworksBuildPhase section */
61 | 83BEF1D41B5453F4006F38C4 /* Frameworks */ = {
62 | isa = PBXFrameworksBuildPhase;
63 | buildActionMask = 2147483647;
64 | files = (
65 | );
66 | runOnlyForDeploymentPostprocessing = 0;
67 | };
68 | /* End PBXFrameworksBuildPhase section */
69 |
70 | /* Begin PBXGroup section */
71 | 83BEF18A1B5453D8006F38C4 = {
72 | isa = PBXGroup;
73 | children = (
74 | 83BEF1CC1B5453F4006F38C4 /* Ti 5.2.0 WatchKit App */,
75 | 83BEF1DB1B5453F4006F38C4 /* Ti 5.2.0 WatchKit Extension */,
76 | 83BEF1941B5453D8006F38C4 /* Products */,
77 | );
78 | sourceTree = "";
79 | };
80 | 83BEF1941B5453D8006F38C4 /* Products */ = {
81 | isa = PBXGroup;
82 | children = (
83 | 83BEF1CB1B5453F4006F38C4 /* Ti 5.2.0 WatchKit App.app */,
84 | 83BEF1D71B5453F4006F38C4 /* Ti 5.2.0 WatchKit Extension.appex */,
85 | );
86 | name = Products;
87 | sourceTree = "";
88 | };
89 | 83BEF1CC1B5453F4006F38C4 /* Ti 5.2.0 WatchKit App */ = {
90 | isa = PBXGroup;
91 | children = (
92 | 83BEF1CD1B5453F4006F38C4 /* Interface.storyboard */,
93 | 83BEF1D01B5453F4006F38C4 /* Assets.xcassets */,
94 | 83BEF1D21B5453F4006F38C4 /* Info.plist */,
95 | );
96 | path = "Ti 5.2.0 WatchKit App";
97 | sourceTree = "";
98 | };
99 | 83BEF1DB1B5453F4006F38C4 /* Ti 5.2.0 WatchKit Extension */ = {
100 | isa = PBXGroup;
101 | children = (
102 | 83BEF1DE1B5453F4006F38C4 /* InterfaceController.h */,
103 | 83BEF1DF1B5453F4006F38C4 /* InterfaceController.m */,
104 | 83BEF1E11B5453F4006F38C4 /* ExtensionDelegate.h */,
105 | 83BEF1E21B5453F4006F38C4 /* ExtensionDelegate.m */,
106 | 83BEF1E41B5453F4006F38C4 /* NotificationController.h */,
107 | 83BEF1E51B5453F4006F38C4 /* NotificationController.m */,
108 | 83BEF1EA1B5453F4006F38C4 /* Assets.xcassets */,
109 | 83BEF1EC1B5453F4006F38C4 /* Info.plist */,
110 | 83BEF1DC1B5453F4006F38C4 /* Supporting Files */,
111 | );
112 | path = "Ti 5.2.0 WatchKit Extension";
113 | sourceTree = "";
114 | };
115 | 83BEF1DC1B5453F4006F38C4 /* Supporting Files */ = {
116 | isa = PBXGroup;
117 | children = (
118 | 83BEF1DD1B5453F4006F38C4 /* PushNotificationPayload.apns */,
119 | );
120 | name = "Supporting Files";
121 | sourceTree = "";
122 | };
123 | /* End PBXGroup section */
124 |
125 | /* Begin PBXNativeTarget section */
126 | 83BEF1CA1B5453F4006F38C4 /* Ti 5.2.0 WatchKit App */ = {
127 | isa = PBXNativeTarget;
128 | buildConfigurationList = 83BEF1F41B5453F4006F38C4 /* Build configuration list for PBXNativeTarget "Ti 5.2.0 WatchKit App" */;
129 | buildPhases = (
130 | 83BEF1C91B5453F4006F38C4 /* Resources */,
131 | 83BEF1F31B5453F4006F38C4 /* Embed App Extensions */,
132 | );
133 | buildRules = (
134 | );
135 | dependencies = (
136 | 83BEF1DA1B5453F4006F38C4 /* PBXTargetDependency */,
137 | );
138 | name = "Ti 5.2.0 WatchKit App";
139 | productName = "Ti 5.2.0 WatchKit App";
140 | productReference = 83BEF1CB1B5453F4006F38C4 /* Ti 5.2.0 WatchKit App.app */;
141 | productType = "com.apple.product-type.application.watchapp2";
142 | };
143 | 83BEF1D61B5453F4006F38C4 /* Ti 5.2.0 WatchKit Extension */ = {
144 | isa = PBXNativeTarget;
145 | buildConfigurationList = 83BEF1F01B5453F4006F38C4 /* Build configuration list for PBXNativeTarget "Ti 5.2.0 WatchKit Extension" */;
146 | buildPhases = (
147 | 83BEF1D31B5453F4006F38C4 /* Sources */,
148 | 83BEF1D41B5453F4006F38C4 /* Frameworks */,
149 | 83BEF1D51B5453F4006F38C4 /* Resources */,
150 | );
151 | buildRules = (
152 | );
153 | dependencies = (
154 | );
155 | name = "Ti 5.2.0 WatchKit Extension";
156 | productName = "Ti 5.2.0 WatchKit Extension";
157 | productReference = 83BEF1D71B5453F4006F38C4 /* Ti 5.2.0 WatchKit Extension.appex */;
158 | productType = "com.apple.product-type.watchkit2-extension";
159 | };
160 | /* End PBXNativeTarget section */
161 |
162 | /* Begin PBXProject section */
163 | 83BEF18B1B5453D8006F38C4 /* Project object */ = {
164 | isa = PBXProject;
165 | attributes = {
166 | LastUpgradeCheck = 0700;
167 | ORGANIZATIONNAME = Appcelerator;
168 | TargetAttributes = {
169 | 83BEF1CA1B5453F4006F38C4 = {
170 | CreatedOnToolsVersion = 7.0;
171 | };
172 | 83BEF1D61B5453F4006F38C4 = {
173 | CreatedOnToolsVersion = 7.0;
174 | };
175 | };
176 | };
177 | buildConfigurationList = 83BEF18E1B5453D8006F38C4 /* Build configuration list for PBXProject "Ti 5.2.0" */;
178 | compatibilityVersion = "Xcode 3.2";
179 | developmentRegion = English;
180 | hasScannedForEncodings = 0;
181 | knownRegions = (
182 | en,
183 | Base,
184 | );
185 | mainGroup = 83BEF18A1B5453D8006F38C4;
186 | productRefGroup = 83BEF1941B5453D8006F38C4 /* Products */;
187 | projectDirPath = "";
188 | projectRoot = "";
189 | targets = (
190 | 83BEF1CA1B5453F4006F38C4 /* Ti 5.2.0 WatchKit App */,
191 | 83BEF1D61B5453F4006F38C4 /* Ti 5.2.0 WatchKit Extension */,
192 | );
193 | };
194 | /* End PBXProject section */
195 |
196 | /* Begin PBXResourcesBuildPhase section */
197 | 83BEF1C91B5453F4006F38C4 /* Resources */ = {
198 | isa = PBXResourcesBuildPhase;
199 | buildActionMask = 2147483647;
200 | files = (
201 | 83BEF1D11B5453F4006F38C4 /* Assets.xcassets in Resources */,
202 | 83BEF1CF1B5453F4006F38C4 /* Interface.storyboard in Resources */,
203 | );
204 | runOnlyForDeploymentPostprocessing = 0;
205 | };
206 | 83BEF1D51B5453F4006F38C4 /* Resources */ = {
207 | isa = PBXResourcesBuildPhase;
208 | buildActionMask = 2147483647;
209 | files = (
210 | 83BEF1EB1B5453F4006F38C4 /* Assets.xcassets in Resources */,
211 | );
212 | runOnlyForDeploymentPostprocessing = 0;
213 | };
214 | /* End PBXResourcesBuildPhase section */
215 |
216 | /* Begin PBXSourcesBuildPhase section */
217 | 83BEF1D31B5453F4006F38C4 /* Sources */ = {
218 | isa = PBXSourcesBuildPhase;
219 | buildActionMask = 2147483647;
220 | files = (
221 | 83BEF1E31B5453F4006F38C4 /* ExtensionDelegate.m in Sources */,
222 | 83BEF1E01B5453F4006F38C4 /* InterfaceController.m in Sources */,
223 | 83BEF1E61B5453F4006F38C4 /* NotificationController.m in Sources */,
224 | );
225 | runOnlyForDeploymentPostprocessing = 0;
226 | };
227 | /* End PBXSourcesBuildPhase section */
228 |
229 | /* Begin PBXTargetDependency section */
230 | 83BEF1DA1B5453F4006F38C4 /* PBXTargetDependency */ = {
231 | isa = PBXTargetDependency;
232 | target = 83BEF1D61B5453F4006F38C4 /* Ti 5.2.0 WatchKit Extension */;
233 | targetProxy = 83BEF1D91B5453F4006F38C4 /* PBXContainerItemProxy */;
234 | };
235 | /* End PBXTargetDependency section */
236 |
237 | /* Begin PBXVariantGroup section */
238 | 83BEF1CD1B5453F4006F38C4 /* Interface.storyboard */ = {
239 | isa = PBXVariantGroup;
240 | children = (
241 | 83BEF1CE1B5453F4006F38C4 /* Base */,
242 | );
243 | name = Interface.storyboard;
244 | sourceTree = "";
245 | };
246 | /* End PBXVariantGroup section */
247 |
248 | /* Begin XCBuildConfiguration section */
249 | 83BEF1BE1B5453D8006F38C4 /* Debug */ = {
250 | isa = XCBuildConfiguration;
251 | buildSettings = {
252 | ALWAYS_SEARCH_USER_PATHS = NO;
253 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
254 | CLANG_CXX_LIBRARY = "libc++";
255 | CLANG_ENABLE_MODULES = YES;
256 | CLANG_ENABLE_OBJC_ARC = YES;
257 | CLANG_WARN_BOOL_CONVERSION = YES;
258 | CLANG_WARN_CONSTANT_CONVERSION = YES;
259 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
260 | CLANG_WARN_EMPTY_BODY = YES;
261 | CLANG_WARN_ENUM_CONVERSION = YES;
262 | CLANG_WARN_INT_CONVERSION = YES;
263 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
264 | CLANG_WARN_UNREACHABLE_CODE = YES;
265 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
266 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
267 | COPY_PHASE_STRIP = NO;
268 | DEBUG_INFORMATION_FORMAT = dwarf;
269 | ENABLE_STRICT_OBJC_MSGSEND = YES;
270 | ENABLE_TESTABILITY = YES;
271 | GCC_C_LANGUAGE_STANDARD = gnu99;
272 | GCC_DYNAMIC_NO_PIC = NO;
273 | GCC_NO_COMMON_BLOCKS = YES;
274 | GCC_OPTIMIZATION_LEVEL = 0;
275 | GCC_PREPROCESSOR_DEFINITIONS = (
276 | "DEBUG=1",
277 | "$(inherited)",
278 | );
279 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
280 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
281 | GCC_WARN_UNDECLARED_SELECTOR = YES;
282 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
283 | GCC_WARN_UNUSED_FUNCTION = YES;
284 | GCC_WARN_UNUSED_VARIABLE = YES;
285 | IPHONEOS_DEPLOYMENT_TARGET = 9.0;
286 | MTL_ENABLE_DEBUG_INFO = YES;
287 | ONLY_ACTIVE_ARCH = YES;
288 | SDKROOT = iphoneos;
289 | TARGETED_DEVICE_FAMILY = "1,2";
290 | };
291 | name = Debug;
292 | };
293 | 83BEF1BF1B5453D8006F38C4 /* Release */ = {
294 | isa = XCBuildConfiguration;
295 | buildSettings = {
296 | ALWAYS_SEARCH_USER_PATHS = NO;
297 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
298 | CLANG_CXX_LIBRARY = "libc++";
299 | CLANG_ENABLE_MODULES = YES;
300 | CLANG_ENABLE_OBJC_ARC = YES;
301 | CLANG_WARN_BOOL_CONVERSION = YES;
302 | CLANG_WARN_CONSTANT_CONVERSION = YES;
303 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
304 | CLANG_WARN_EMPTY_BODY = YES;
305 | CLANG_WARN_ENUM_CONVERSION = YES;
306 | CLANG_WARN_INT_CONVERSION = YES;
307 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
308 | CLANG_WARN_UNREACHABLE_CODE = YES;
309 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
310 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
311 | COPY_PHASE_STRIP = NO;
312 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
313 | ENABLE_NS_ASSERTIONS = NO;
314 | ENABLE_STRICT_OBJC_MSGSEND = YES;
315 | GCC_C_LANGUAGE_STANDARD = gnu99;
316 | GCC_NO_COMMON_BLOCKS = YES;
317 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
318 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
319 | GCC_WARN_UNDECLARED_SELECTOR = YES;
320 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
321 | GCC_WARN_UNUSED_FUNCTION = YES;
322 | GCC_WARN_UNUSED_VARIABLE = YES;
323 | IPHONEOS_DEPLOYMENT_TARGET = 9.0;
324 | MTL_ENABLE_DEBUG_INFO = NO;
325 | SDKROOT = iphoneos;
326 | TARGETED_DEVICE_FAMILY = "1,2";
327 | VALIDATE_PRODUCT = YES;
328 | };
329 | name = Release;
330 | };
331 | 83BEF1F11B5453F4006F38C4 /* Debug */ = {
332 | isa = XCBuildConfiguration;
333 | buildSettings = {
334 | "CODE_SIGN_IDENTITY[sdk=watchos*]" = "iPhone Developer";
335 | INFOPLIST_FILE = "Ti 5.2.0 WatchKit Extension/Info.plist";
336 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
337 | PRODUCT_BUNDLE_IDENTIFIER = com.appcelerator.sample.ti520.watchkitapp.watchkitextension;
338 | PRODUCT_NAME = "${TARGET_NAME}";
339 | SDKROOT = watchos;
340 | SKIP_INSTALL = YES;
341 | TARGETED_DEVICE_FAMILY = 4;
342 | WATCHOS_DEPLOYMENT_TARGET = 2.0;
343 | };
344 | name = Debug;
345 | };
346 | 83BEF1F21B5453F4006F38C4 /* Release */ = {
347 | isa = XCBuildConfiguration;
348 | buildSettings = {
349 | "CODE_SIGN_IDENTITY[sdk=watchos*]" = "iPhone Developer";
350 | INFOPLIST_FILE = "Ti 5.2.0 WatchKit Extension/Info.plist";
351 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
352 | PRODUCT_BUNDLE_IDENTIFIER = com.appcelerator.sample.ti520.watchkitapp.watchkitextension;
353 | PRODUCT_NAME = "${TARGET_NAME}";
354 | SDKROOT = watchos;
355 | SKIP_INSTALL = YES;
356 | TARGETED_DEVICE_FAMILY = 4;
357 | WATCHOS_DEPLOYMENT_TARGET = 2.0;
358 | };
359 | name = Release;
360 | };
361 | 83BEF1F51B5453F4006F38C4 /* Debug */ = {
362 | isa = XCBuildConfiguration;
363 | buildSettings = {
364 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
365 | "CODE_SIGN_IDENTITY[sdk=watchos*]" = "iPhone Developer";
366 | IBSC_MODULE = Ti_5_2_0_WatchKit_Extension;
367 | INFOPLIST_FILE = "Ti 5.2.0 WatchKit App/Info.plist";
368 | PRODUCT_BUNDLE_IDENTIFIER = com.appcelerator.sample.ti520.watchkitapp;
369 | PRODUCT_NAME = "$(TARGET_NAME)";
370 | SDKROOT = watchos;
371 | SKIP_INSTALL = YES;
372 | TARGETED_DEVICE_FAMILY = 4;
373 | WATCHOS_DEPLOYMENT_TARGET = 2.0;
374 | };
375 | name = Debug;
376 | };
377 | 83BEF1F61B5453F4006F38C4 /* Release */ = {
378 | isa = XCBuildConfiguration;
379 | buildSettings = {
380 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
381 | "CODE_SIGN_IDENTITY[sdk=watchos*]" = "iPhone Developer";
382 | IBSC_MODULE = Ti_5_2_0_WatchKit_Extension;
383 | INFOPLIST_FILE = "Ti 5.2.0 WatchKit App/Info.plist";
384 | PRODUCT_BUNDLE_IDENTIFIER = com.appcelerator.sample.ti520.watchkitapp;
385 | PRODUCT_NAME = "$(TARGET_NAME)";
386 | SDKROOT = watchos;
387 | SKIP_INSTALL = YES;
388 | TARGETED_DEVICE_FAMILY = 4;
389 | WATCHOS_DEPLOYMENT_TARGET = 2.0;
390 | };
391 | name = Release;
392 | };
393 | /* End XCBuildConfiguration section */
394 |
395 | /* Begin XCConfigurationList section */
396 | 83BEF18E1B5453D8006F38C4 /* Build configuration list for PBXProject "Ti 5.2.0" */ = {
397 | isa = XCConfigurationList;
398 | buildConfigurations = (
399 | 83BEF1BE1B5453D8006F38C4 /* Debug */,
400 | 83BEF1BF1B5453D8006F38C4 /* Release */,
401 | );
402 | defaultConfigurationIsVisible = 0;
403 | defaultConfigurationName = Release;
404 | };
405 | 83BEF1F01B5453F4006F38C4 /* Build configuration list for PBXNativeTarget "Ti 5.2.0 WatchKit Extension" */ = {
406 | isa = XCConfigurationList;
407 | buildConfigurations = (
408 | 83BEF1F11B5453F4006F38C4 /* Debug */,
409 | 83BEF1F21B5453F4006F38C4 /* Release */,
410 | );
411 | defaultConfigurationIsVisible = 0;
412 | };
413 | 83BEF1F41B5453F4006F38C4 /* Build configuration list for PBXNativeTarget "Ti 5.2.0 WatchKit App" */ = {
414 | isa = XCConfigurationList;
415 | buildConfigurations = (
416 | 83BEF1F51B5453F4006F38C4 /* Debug */,
417 | 83BEF1F61B5453F4006F38C4 /* Release */,
418 | );
419 | defaultConfigurationIsVisible = 0;
420 | };
421 | /* End XCConfigurationList section */
422 | };
423 | rootObject = 83BEF18B1B5453D8006F38C4 /* Project object */;
424 | }
425 |
--------------------------------------------------------------------------------
/platform/ios/_LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/plugins/ti.alloy/hooks/alloy.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Alloy
3 | * Copyright (c) 2012 by Appcelerator, Inc. All Rights Reserved.
4 | * See LICENSE for more information on licensing.
5 | */
6 |
7 | exports.cliVersion = '>=3.X';
8 | exports.version = '1.0.0';
9 | var SILENT = true;
10 |
11 | exports.init = function (logger, config, cli, appc) {
12 | var path = require('path'),
13 | fs = require('fs'),
14 | afs = appc.fs,
15 | i18n = appc.i18n(__dirname),
16 | __ = i18n.__,
17 | __n = i18n.__n,
18 | pkginfo = appc.pkginfo.package(module),
19 | exec = require('child_process').exec,
20 | spawn = require('child_process').spawn,
21 | parallel = appc.async.parallel;
22 |
23 | if(!process.env.sdk) {
24 | process.env.sdk = cli.sdk.name;
25 | }
26 |
27 | function run(deviceFamily, deployType, target, finished, silent) {
28 | var appDir = path.join(cli.argv['project-dir'], 'app');
29 | if (!afs.exists(appDir)) {
30 | logger.info(__('Project not an Alloy app, continuing'));
31 | finished();
32 | return;
33 | }
34 | logger.info(__('Found Alloy app in %s', appDir.cyan));
35 |
36 | // TODO: Make this check specific to a TiSDK version
37 | // create a .alloynewcli file to tell old plugins not to run
38 | var buildDir = path.join(cli.argv['project-dir'], 'build');
39 | if (!afs.exists(buildDir)) {
40 | fs.mkdirSync(buildDir);
41 | }
42 | fs.writeFileSync(path.join(buildDir, '.alloynewcli'), '');
43 |
44 | var cRequire = afs.resolvePath(__dirname, '..', 'Alloy', 'commands', 'compile', 'index.js'),
45 | config = {
46 | platform: /(?:iphone|ipad)/.test(cli.argv.platform) ? 'ios' : cli.argv.platform,
47 | version: '0',
48 | simtype: 'none',
49 | devicefamily: /(?:iphone|ios)/.test(cli.argv.platform) ? deviceFamily : 'none',
50 | deploytype: deployType || cli.argv['deploy-type'] || 'development',
51 | target: target
52 | };
53 | if(silent) {
54 | // turn off all logging output for code analyzer build hook
55 | config.noBanner = 'true';
56 | config.logLevel = '-1';
57 | }
58 |
59 | config = Object.keys(config).map(function (c) {
60 | return c + '=' + config[c];
61 | }).join(',');
62 |
63 | if (afs.exists(cRequire)) {
64 | // we're being invoked from the actual alloy directory!
65 | // no need to subprocess, just require() and run
66 | var origLimit = Error.stackTraceLimit;
67 | Error.stackTraceLimit = Infinity;
68 | try {
69 | require(cRequire)({}, {
70 | config: config,
71 | outputPath: cli.argv['project-dir'],
72 | _version: pkginfo.version
73 | });
74 | } catch (e) {
75 | logger.error(__('Alloy compiler failed'));
76 | e.toString().split('\n').forEach(function (line) {
77 | if (line) { logger.error(line); }
78 | });
79 | process.exit(1);
80 | }
81 | Error.stackTraceLimit = origLimit;
82 | finished();
83 | } else {
84 | // we have no clue where alloy is installed, so we're going to subprocess
85 | // alloy and hope it's in the system path or a well known place
86 | var paths = {};
87 | var locatorCmd = process.platform === 'win32' ? 'where' : 'which';
88 | parallel(this, ['alloy', 'node'].map(function (bin) {
89 | return function (done) {
90 | var envName = 'ALLOY_' + (bin === 'node' ? 'NODE_' : '') + 'PATH';
91 |
92 | paths[bin] = process.env[envName];
93 | if (paths[bin]) {
94 | done();
95 | } else if (process.platform === 'win32' && bin === 'alloy') {
96 | paths.alloy = 'alloy.cmd';
97 | done();
98 | } else {
99 | exec(locatorCmd + ' ' + bin, function (err, stdout, strerr) {
100 | if (!err) {
101 | paths[bin] = stdout.trim();
102 | done();
103 | } else {
104 | parallel(this, [
105 | '/usr/local/bin/' + bin,
106 | '/opt/local/bin/' + bin,
107 | path.join(process.env.HOME, 'local/bin', bin),
108 | '/opt/bin/' + bin,
109 | '/usr/bin/' + bin
110 | ].map(function (p) {
111 | return function (cb) {
112 | if (afs.exists(p)) { paths[bin] = p; }
113 | cb();
114 | };
115 | }), done);
116 | }
117 | });
118 | }
119 | };
120 | }), function () {
121 |
122 | // compose alloy command execution
123 | var cmd = [paths.node, paths.alloy, 'compile', appDir, '--config', config];
124 | if (cli.argv['no-colors'] || cli.argv['color'] === false) { cmd.push('--no-colors'); }
125 |
126 | // process each line of output from alloy
127 | function checkLine(line) {
128 | var re = new RegExp(
129 | '^(?:\u001b\\[\\d+m)?\\[?(' +
130 | logger.getLevels().join('|') +
131 | ')\\]?\s*(?:\u001b\\[\\d+m)?(.*)', 'i'
132 | );
133 | if (line) {
134 | var m = line.match(re);
135 | if (m) {
136 | logger[m[1].toLowerCase()](m[2].trim());
137 | } else {
138 | logger.debug(line);
139 | }
140 | }
141 | }
142 |
143 | // execute alloy in os-specific manner
144 | var child;
145 | if (process.platform === 'win32' && paths.alloy === 'alloy.cmd') {
146 | cmd.shift();
147 | logger.info(__('Executing Alloy compile: %s',
148 | ['cmd','/s','/c'].concat(cmd).join(' ').cyan));
149 |
150 | // arg processing from https://github.com/MarcDiethelm/superspawn
151 | child = spawn('cmd', [['/s', '/c', '"' +
152 | cmd.map(function(a) {
153 | if (/^[^"].* .*[^"]/.test(a)) return '"'+a+'"'; return a;
154 | }).join(" ") + '"'].join(" ")], {
155 | stdio: 'inherit',
156 | windowsVerbatimArguments: true
157 | }
158 | );
159 | } else {
160 | logger.info(__('Executing Alloy compile: %s', cmd.join(' ').cyan));
161 | child = spawn(cmd.shift(), cmd);
162 | child.stdout.on('data', function (data) {
163 | data.toString().split('\n').forEach(checkLine);
164 | });
165 | child.stderr.on('data', function (data) {
166 | data.toString().split('\n').forEach(checkLine);
167 | });
168 | }
169 |
170 | // handle the completion of alloy, success or otherwise
171 | child.on('exit', function (code) {
172 | if (code) {
173 | logger.error(__('Alloy compiler failed'));
174 | process.exit(1);
175 | } else {
176 | logger.info(__('Alloy compiler completed successfully'));
177 |
178 | afs.exists(path.join(cli.argv["project-dir"], 'build', 'i18n')) && process.argv.push('--i18n-dir', 'build');
179 | afs.exists(path.join(cli.argv["project-dir"], 'build', 'platform')) && (cli.argv['platform-dir'] = 'build/platform');
180 | }
181 | finished();
182 | });
183 |
184 | });
185 | }
186 | }
187 |
188 | cli.addHook('build.pre.compile', function (build, finished) {
189 | var deployType = build.deployType,
190 | target = build.target;
191 |
192 | run(build.deviceFamily, deployType, target, finished);
193 | });
194 |
195 | cli.addHook('codeprocessor.pre.run', function (build, finished) {
196 | run('none', 'development', undefined, finished, SILENT);
197 | });
198 | };
199 |
--------------------------------------------------------------------------------
/plugins/ti.alloy/hooks/deepclean.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Alloy
3 | * Copyright (c) 2014 by Appcelerator, Inc. All Rights Reserved.
4 | * See LICENSE for more information on licensing.
5 | */
6 |
7 | exports.cliVersion = '>=3.X';
8 | var SILENT = true;
9 |
10 | exports.init = function (logger, config, cli, appc) {
11 | var path = require('path'),
12 | fs = require('fs'),
13 | afs = appc.fs;
14 |
15 | function run(finished) {
16 | if(cli.argv['shallow'] === '') {
17 | logger.info('Not cleaning the Resources directory');
18 | finished();
19 | return;
20 | }
21 | var appDir = path.join(cli.argv['project-dir'], 'app');
22 | if (!afs.exists(appDir)) {
23 | logger.debug('Project not an Alloy app, exiting.');
24 | finished();
25 | return;
26 | }
27 |
28 | var resourcesDir = path.join(cli.argv['project-dir'], 'Resources');
29 | if (!afs.exists(resourcesDir)) {
30 | logger.debug('Resources directory does not exist.');
31 | finished();
32 | return;
33 | }
34 | rmdir(resourcesDir, fs, path, logger);
35 | logger.debug('Resources directory of %s has been emptied', appDir.cyan);
36 | finished();
37 | }
38 |
39 | cli.addHook('clean.post', function (build, finished) {
40 | run(finished);
41 | });
42 |
43 | };
44 |
45 | function rmdir(dirPath, fs, path, logger, removeSelf) {
46 | var files;
47 | try {
48 | files = fs.readdirSync(dirPath);
49 | }
50 | catch(e) {
51 | return;
52 | }
53 | if (files.length > 0) {
54 | for (var i = 0; i < files.length; i++) {
55 | var filePath = path.join(dirPath, files[i]);
56 | if (fs.statSync(filePath).isFile()) {
57 | fs.unlinkSync(filePath);
58 | } else {
59 | rmdir(filePath, fs, path, logger, true);
60 | }
61 | }
62 | }
63 | if (removeSelf) {
64 | fs.rmdirSync(dirPath);
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/plugins/ti.alloy/plugin.py:
--------------------------------------------------------------------------------
1 | import os, sys, subprocess, hashlib
2 |
3 | import subprocess
4 |
5 | def check_output(*popenargs, **kwargs):
6 | r"""Run command with arguments and return its output as a byte string.
7 |
8 | Backported from Python 2.7 as it's implemented as pure python on stdlib.
9 |
10 | >>> check_output(['/usr/bin/python', '--version'])
11 | Python 2.6.2
12 | """
13 | process = subprocess.Popen(stdout=subprocess.PIPE, *popenargs, **kwargs)
14 | output, unused_err = process.communicate()
15 | retcode = process.poll()
16 | if retcode:
17 | cmd = kwargs.get("args")
18 | if cmd is None:
19 | cmd = popenargs[0]
20 | error = subprocess.CalledProcessError(retcode, cmd)
21 | error.output = output
22 | raise error
23 | return output
24 |
25 | def compile(config):
26 | paths = {}
27 | binaries = ["alloy","node"]
28 |
29 | dotAlloy = os.path.abspath(os.path.join(config['project_dir'], 'build', '.alloynewcli'))
30 | if os.path.exists(dotAlloy):
31 | print "[DEBUG] build/.alloynewcli file found, skipping plugin..."
32 | os.remove(dotAlloy)
33 | else:
34 | for binary in binaries:
35 | try:
36 | # see if the environment variable is defined
37 | paths[binary] = os.environ["ALLOY_" + ("NODE_" if binary == "node" else "") + "PATH"]
38 | except KeyError as ex:
39 | # next try PATH, and then our guess paths
40 | if sys.platform == "darwin" or sys.platform.startswith('linux'):
41 | userPath = os.environ["HOME"]
42 | guessPaths = [
43 | "/usr/local/bin/"+binary,
44 | "/opt/local/bin/"+binary,
45 | userPath+"/local/bin/"+binary,
46 | "/opt/bin/"+binary,
47 | "/usr/bin/"+binary,
48 | "/usr/local/share/npm/bin/"+binary
49 | ]
50 |
51 | try:
52 | binaryPath = check_output(["which",binary], stderr=subprocess.STDOUT).strip()
53 | print "[DEBUG] %s installed at '%s'" % (binary,binaryPath)
54 | except:
55 | print "[WARN] Couldn't find %s on your PATH:" % binary
56 | print "[WARN] %s" % os.environ["PATH"]
57 | print "[WARN]"
58 | print "[WARN] Checking for %s in a few default locations:" % binary
59 | for p in guessPaths:
60 | sys.stdout.write("[WARN] %s -> " % p)
61 | if os.path.exists(p):
62 | binaryPath = p
63 | print "FOUND"
64 | break
65 | else:
66 | print "not found"
67 | binaryPath = None
68 |
69 | if binaryPath is None:
70 | print "[ERROR] Couldn't find %s" % binary
71 | sys.exit(1)
72 | else:
73 | paths[binary] = binaryPath
74 |
75 | # no guesses on windows, just use the PATH
76 | elif sys.platform == "win32":
77 | paths["alloy"] = "alloy.cmd"
78 |
79 | f = os.path.abspath(os.path.join(config['project_dir'], 'app'))
80 | if os.path.exists(f):
81 | print "[INFO] alloy app found at %s" % f
82 | rd = os.path.abspath(os.path.join(config['project_dir'], 'Resources'))
83 |
84 | devicefamily = 'none'
85 | simtype = 'none'
86 | version = '0'
87 | deploytype = 'development'
88 |
89 | if config['platform']==u'ios':
90 | version = config['iphone_version']
91 | devicefamily = config['devicefamily']
92 | deploytype = config['deploytype']
93 | if config['platform']==u'android':
94 | builder = config['android_builder']
95 | version = builder.tool_api_level
96 | deploytype = config['deploy_type']
97 | if config['platform']==u'mobileweb':
98 | builder = config['mobileweb_builder']
99 | deploytype = config['deploytype']
100 |
101 | cfg = "platform=%s,version=%s,simtype=%s,devicefamily=%s,deploytype=%s," % (config['platform'],version,simtype,devicefamily,deploytype)
102 |
103 | if sys.platform == "win32":
104 | cmd = [paths["alloy"], "compile", f, "--no-colors", "--config", cfg]
105 | else:
106 | cmd = [paths["node"], paths["alloy"], "compile", f, "--no-colors", "--config", cfg]
107 |
108 | print "[INFO] Executing Alloy compile:"
109 | print "[INFO] %s" % " ".join(cmd)
110 |
111 | try:
112 | print check_output(cmd, stderr=subprocess.STDOUT)
113 | except subprocess.CalledProcessError as ex:
114 | if hasattr(ex, 'output'):
115 | print ex.output
116 | print "[ERROR] Alloy compile failed"
117 | retcode = 1
118 | if hasattr(ex, 'returncode'):
119 | retcode = ex.returncode
120 | sys.exit(retcode)
121 | except EnvironmentError as ex:
122 | print "[ERROR] Unexpected error with Alloy compiler plugin: %s" % ex.strerror
123 | sys.exit(2)
124 |
--------------------------------------------------------------------------------
/plugins/ti.version/1.0/hooks/version.js:
--------------------------------------------------------------------------------
1 | exports.init = function(logger, config, cli, appc) {
2 | if (cli.tiapp.properties['ti.version.range']) {
3 | if (!appc.version.satisfies(cli.sdk.manifest.name, cli.tiapp.properties['ti.version.range'].value)) {
4 | logger.error('This app requires Titanium SDK ' + cli.tiapp.properties['ti.version.range'].value + ' instead of ' + cli.sdk.name + ' (' + cli.sdk.manifest.name + ')');
5 | process.exit(1);
6 | }
7 | }
8 | };
9 |
--------------------------------------------------------------------------------
/tiapp.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | com.appcelerator.sample.ti520
5 | Ti 5.2.0
6 | 1.0
7 | Appcelerator
8 | http://www.appcelerator.com
9 | This app demonstrates new features in Titanium 5.2.0
10 | 2016 by Appcelerator, Inc.
11 | appicon.png
12 | false
13 |
14 | true
15 | false
16 | 11111111-1111-1111-1111-111111111111
17 | dp
18 | >=5.2.2 <5.3
19 |
20 |
21 | 9.0
22 |
26 | true
27 |
28 | #C7172C
29 |
30 | true
31 |
32 |
33 |
34 | UIRequiresFullScreen
35 |
36 |
37 | NSUserActivityTypes
38 |
39 | com.appcelerator.sample.ti520.tab
40 |
41 | UISupportedInterfaceOrientations~iphone
42 |
43 | UIInterfaceOrientationPortrait
44 | UIInterfaceOrientationLandscapeLeft
45 | UIInterfaceOrientationLandscapeRight
46 |
47 | UISupportedInterfaceOrientations~ipad
48 |
49 | UIInterfaceOrientationPortrait
50 | UIInterfaceOrientationPortraitUpsideDown
51 | UIInterfaceOrientationLandscapeLeft
52 | UIInterfaceOrientationLandscapeRight
53 |
54 | UIRequiresPersistentWiFi
55 |
56 | UIPrerenderedIcon
57 |
58 | UIStatusBarHidden
59 |
60 | UIStatusBarStyle
61 | UIStatusBarStyleLightContent
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 | ti.map
99 |
100 |
101 | true
102 | true
103 | true
104 | false
105 | false
106 |
107 | 5.2.2.GA
108 |
109 | ti.alloy
110 | ti.version
111 |
112 |
113 |
--------------------------------------------------------------------------------