@maccesar/titools 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS-TEMPLATE.md +173 -0
- package/README.md +867 -0
- package/agents/ti-researcher.md +108 -0
- package/bin/titools.js +53 -0
- package/lib/commands/agents.js +126 -0
- package/lib/commands/install.js +188 -0
- package/lib/commands/uninstall.js +215 -0
- package/lib/commands/update.js +159 -0
- package/lib/config.js +119 -0
- package/lib/downloader.js +153 -0
- package/lib/installer.js +253 -0
- package/lib/platform.js +108 -0
- package/lib/symlink.js +142 -0
- package/lib/utils.js +270 -0
- package/package.json +67 -0
- package/skills/alloy-expert/SKILL.md +247 -0
- package/skills/alloy-expert/assets/ControllerAutoCleanup.js +182 -0
- package/skills/alloy-expert/references/alloy-structure.md +381 -0
- package/skills/alloy-expert/references/anti-patterns.md +133 -0
- package/skills/alloy-expert/references/code-conventions.md +469 -0
- package/skills/alloy-expert/references/contracts.md +280 -0
- package/skills/alloy-expert/references/controller-patterns.md +520 -0
- package/skills/alloy-expert/references/error-handling.md +484 -0
- package/skills/alloy-expert/references/examples.md +735 -0
- package/skills/alloy-expert/references/migration-patterns.md +298 -0
- package/skills/alloy-expert/references/patterns.md +448 -0
- package/skills/alloy-expert/references/performance-patterns.md +855 -0
- package/skills/alloy-expert/references/security-patterns.md +847 -0
- package/skills/alloy-expert/references/state-management.md +779 -0
- package/skills/alloy-expert/references/testing.md +872 -0
- package/skills/alloy-guides/SKILL.md +214 -0
- package/skills/alloy-guides/references/CLI_TASKS.md +243 -0
- package/skills/alloy-guides/references/CONCEPTS.md +191 -0
- package/skills/alloy-guides/references/CONTROLLERS.md +298 -0
- package/skills/alloy-guides/references/MODELS.md +1028 -0
- package/skills/alloy-guides/references/PURGETSS.md +56 -0
- package/skills/alloy-guides/references/VIEWS_DYNAMIC.md +242 -0
- package/skills/alloy-guides/references/VIEWS_STYLES.md +388 -0
- package/skills/alloy-guides/references/VIEWS_WITHOUT_CONTROLLERS.md +109 -0
- package/skills/alloy-guides/references/VIEWS_XML.md +558 -0
- package/skills/alloy-guides/references/WIDGETS.md +176 -0
- package/skills/alloy-howtos/SKILL.md +203 -0
- package/skills/alloy-howtos/references/best_practices.md +138 -0
- package/skills/alloy-howtos/references/cli_reference.md +253 -0
- package/skills/alloy-howtos/references/config_files.md +87 -0
- package/skills/alloy-howtos/references/custom_tags.md +147 -0
- package/skills/alloy-howtos/references/debugging_troubleshooting.md +101 -0
- package/skills/alloy-howtos/references/samples.md +167 -0
- package/skills/purgetss/SKILL.md +442 -0
- package/skills/purgetss/assets/purgetss.config.cjs +17 -0
- package/skills/purgetss/references/EXAMPLES.md +247 -0
- package/skills/purgetss/references/animation-system.md +1294 -0
- package/skills/purgetss/references/apply-directive.md +375 -0
- package/skills/purgetss/references/arbitrary-values.md +612 -0
- package/skills/purgetss/references/class-index.md +1350 -0
- package/skills/purgetss/references/cli-commands.md +948 -0
- package/skills/purgetss/references/configurable-properties.md +654 -0
- package/skills/purgetss/references/custom-rules.md +161 -0
- package/skills/purgetss/references/customization-deep-dive.md +722 -0
- package/skills/purgetss/references/dynamic-component-creation.md +489 -0
- package/skills/purgetss/references/grid-layout.md +455 -0
- package/skills/purgetss/references/icon-fonts.md +609 -0
- package/skills/purgetss/references/installation-setup.md +366 -0
- package/skills/purgetss/references/opacity-modifier.md +291 -0
- package/skills/purgetss/references/platform-modifiers.md +479 -0
- package/skills/purgetss/references/smart-mappings.md +42 -0
- package/skills/purgetss/references/titanium-resets.md +359 -0
- package/skills/purgetss/references/ui-ux-design.md +1526 -0
- package/skills/ti-guides/SKILL.md +94 -0
- package/skills/ti-guides/references/advanced-data-and-images.md +19 -0
- package/skills/ti-guides/references/alloy-cli-advanced.md +84 -0
- package/skills/ti-guides/references/alloy-data-mastery.md +29 -0
- package/skills/ti-guides/references/alloy-widgets-and-themes.md +19 -0
- package/skills/ti-guides/references/android-manifest.md +97 -0
- package/skills/ti-guides/references/app-distribution.md +258 -0
- package/skills/ti-guides/references/application-frameworks.md +377 -0
- package/skills/ti-guides/references/cli-reference.md +402 -0
- package/skills/ti-guides/references/coding-best-practices.md +102 -0
- package/skills/ti-guides/references/commonjs-advanced.md +134 -0
- package/skills/ti-guides/references/hello-world.md +100 -0
- package/skills/ti-guides/references/hyperloop-native-access.md +62 -0
- package/skills/ti-guides/references/javascript-primer.md +411 -0
- package/skills/ti-guides/references/reserved-words.md +36 -0
- package/skills/ti-guides/references/resources.md +183 -0
- package/skills/ti-guides/references/style-and-conventions.md +48 -0
- package/skills/ti-guides/references/tiapp-config.md +609 -0
- package/skills/ti-howtos/SKILL.md +174 -0
- package/skills/ti-howtos/references/android-platform-deep-dives.md +658 -0
- package/skills/ti-howtos/references/automation-fastlane-appium.md +95 -0
- package/skills/ti-howtos/references/buffer-codec-streams.md +140 -0
- package/skills/ti-howtos/references/cross-platform-development.md +348 -0
- package/skills/ti-howtos/references/debugging-profiling.md +543 -0
- package/skills/ti-howtos/references/extending-titanium.md +723 -0
- package/skills/ti-howtos/references/google-maps-v2.md +169 -0
- package/skills/ti-howtos/references/ios-map-kit.md +143 -0
- package/skills/ti-howtos/references/ios-platform-deep-dives.md +783 -0
- package/skills/ti-howtos/references/local-data-sources.md +301 -0
- package/skills/ti-howtos/references/location-and-maps.md +252 -0
- package/skills/ti-howtos/references/media-apis.md +210 -0
- package/skills/ti-howtos/references/notification-services.md +599 -0
- package/skills/ti-howtos/references/remote-data-sources.md +349 -0
- package/skills/ti-howtos/references/tutorials.md +502 -0
- package/skills/ti-howtos/references/using-modules.md +237 -0
- package/skills/ti-howtos/references/web-content-integration.md +307 -0
- package/skills/ti-howtos/references/webpack-build-pipeline.md +78 -0
- package/skills/ti-ui/SKILL.md +179 -0
- package/skills/ti-ui/references/accessibility-deep-dive.md +242 -0
- package/skills/ti-ui/references/animation-and-matrices.md +599 -0
- package/skills/ti-ui/references/application-structures.md +655 -0
- package/skills/ti-ui/references/custom-fonts-styling.md +579 -0
- package/skills/ti-ui/references/event-handling.md +393 -0
- package/skills/ti-ui/references/gestures.md +473 -0
- package/skills/ti-ui/references/icons-and-splash-screens.md +409 -0
- package/skills/ti-ui/references/layouts-and-positioning.md +462 -0
- package/skills/ti-ui/references/listviews-and-performance.md +619 -0
- package/skills/ti-ui/references/orientation.md +362 -0
- package/skills/ti-ui/references/platform-ui-android.md +635 -0
- package/skills/ti-ui/references/platform-ui-ios.md +469 -0
- package/skills/ti-ui/references/scrolling-views.md +252 -0
- package/skills/ti-ui/references/tableviews.md +568 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# Automation with Fastlane and Appium
|
|
2
|
+
|
|
3
|
+
Guide for setting up continuous integration pipelines, automatic testing, and deployment in Titanium.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Automation with Fastlane and Appium](#automation-with-fastlane-and-appium)
|
|
8
|
+
- [Table of Contents](#table-of-contents)
|
|
9
|
+
- [1. UI Testing with Appium](#1-ui-testing-with-appium)
|
|
10
|
+
- [Prerequisites](#prerequisites)
|
|
11
|
+
- [Test Example (Mocha + WebdriverIO)](#test-example-mocha--webdriverio)
|
|
12
|
+
- [2. Automation with Fastlane](#2-automation-with-fastlane)
|
|
13
|
+
- [Titanium Plugins](#titanium-plugins)
|
|
14
|
+
- [Fastfile Configuration](#fastfile-configuration)
|
|
15
|
+
- [3. CI/CD Best Practices](#3-cicd-best-practices)
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## 1. UI Testing with Appium
|
|
20
|
+
|
|
21
|
+
Appium allows for automated functional testing on real devices and simulators.
|
|
22
|
+
|
|
23
|
+
### Prerequisites
|
|
24
|
+
- **Appium Desktop** or CLI.
|
|
25
|
+
- **Mocha** (test runner).
|
|
26
|
+
- **WebdriverIO** (recommended client).
|
|
27
|
+
|
|
28
|
+
### Test Example (Mocha + WebdriverIO)
|
|
29
|
+
```javascript
|
|
30
|
+
const opts = {
|
|
31
|
+
port: 4723,
|
|
32
|
+
capabilities: {
|
|
33
|
+
platformName: "iOS",
|
|
34
|
+
deviceName: "iPhone 15",
|
|
35
|
+
app: "/path/to/your/app.app",
|
|
36
|
+
automationName: "XCUITest"
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
describe("Login Test", () => {
|
|
41
|
+
it("Should login with valid credentials", async () => {
|
|
42
|
+
const client = await wdio.remote(opts);
|
|
43
|
+
const userField = await client.$("~Enter Username"); // Use Accessibility ID
|
|
44
|
+
await userField.setValue("my_user");
|
|
45
|
+
await client.deleteSession();
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## 2. Automation with Fastlane
|
|
51
|
+
|
|
52
|
+
Fastlane automates the building, signing, and uploading process to the stores.
|
|
53
|
+
|
|
54
|
+
### Titanium Plugins
|
|
55
|
+
Install specific plugins in your project:
|
|
56
|
+
```bash
|
|
57
|
+
fastlane add_plugin ti_build_app
|
|
58
|
+
fastlane add_plugin mocha_run_tests
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Fastfile Configuration
|
|
62
|
+
Create a `fastlane/Fastfile` in the root:
|
|
63
|
+
|
|
64
|
+
```ruby
|
|
65
|
+
platform :ios do
|
|
66
|
+
desc "Build for Simulator Tests"
|
|
67
|
+
lane :build_test do
|
|
68
|
+
ti_build_app(
|
|
69
|
+
appc_cli: "ti build -p ios -T simulator --build-only"
|
|
70
|
+
)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
desc "Run UI Tests"
|
|
74
|
+
lane :test do
|
|
75
|
+
build_test
|
|
76
|
+
mocha_run_tests(
|
|
77
|
+
mocha_js_file_name: 'tests/login_test.js'
|
|
78
|
+
)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
desc "Deploy to TestFlight"
|
|
82
|
+
lane :release do
|
|
83
|
+
ti_build_app(
|
|
84
|
+
appc_cli: "ti build -p ios -T dist-appstore --distribution-name 'Your Company' --pp-uuid 'UUID-HERE' --output-dir /dist"
|
|
85
|
+
)
|
|
86
|
+
# Add fastlane pilot command here to upload the .ipa
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## 3. CI/CD Best Practices
|
|
92
|
+
1. **Accessibility IDs**: Always assign `accessibilityLabel` to your components in XML/TSS so Appium can find them easily.
|
|
93
|
+
2. **Environment Lanes**: Define separate lanes for `beta`, `production`, and `test`.
|
|
94
|
+
3. **Profile Management**: Use Fastlane Match to sync certificates and provisioning profiles across the team.
|
|
95
|
+
4. **Snapshots**: Use Fastlane's `snapshot` action to automate App Store screenshot generation.
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# Buffer, Codec, and Streams
|
|
2
|
+
|
|
3
|
+
Guide for advanced binary data manipulation and data flows in Titanium SDK.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Buffer, Codec, and Streams](#buffer-codec-and-streams)
|
|
8
|
+
- [Table of Contents](#table-of-contents)
|
|
9
|
+
- [1. Titanium.Buffer](#1-titaniumbuffer)
|
|
10
|
+
- [Creating Buffers](#creating-buffers)
|
|
11
|
+
- [Common Operations](#common-operations)
|
|
12
|
+
- [2. Titanium.Codec](#2-titaniumcodec)
|
|
13
|
+
- [Encoding Numbers](#encoding-numbers)
|
|
14
|
+
- [Decoding Strings](#decoding-strings)
|
|
15
|
+
- [3. Streams](#3-streams)
|
|
16
|
+
- [Stream Types](#stream-types)
|
|
17
|
+
- [Example: BufferStream](#example-bufferstream)
|
|
18
|
+
- [Example: FileStream (Chunk-based reading)](#example-filestream-chunk-based-reading)
|
|
19
|
+
- [Example: BlobStream (Camera to File)](#example-blobstream-camera-to-file)
|
|
20
|
+
- [4. Best Practices](#4-best-practices)
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## 1. Titanium.Buffer
|
|
25
|
+
|
|
26
|
+
Buffers are mutable and resizable containers for bytes (byte arrays).
|
|
27
|
+
|
|
28
|
+
### Creating Buffers
|
|
29
|
+
```javascript
|
|
30
|
+
// Empty 512-byte buffer
|
|
31
|
+
const buffer1 = Ti.createBuffer({ length: 512 });
|
|
32
|
+
|
|
33
|
+
// Buffer initialized with a string (UTF-8 by default)
|
|
34
|
+
const buffer2 = Ti.createBuffer({ value: "Hello World" });
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Common Operations
|
|
38
|
+
```javascript
|
|
39
|
+
const b1 = Ti.createBuffer({ value: "Part 1. " });
|
|
40
|
+
const b2 = Ti.createBuffer({ value: "Part 2." });
|
|
41
|
+
|
|
42
|
+
// Append
|
|
43
|
+
b1.append(b2);
|
|
44
|
+
|
|
45
|
+
// Truncate
|
|
46
|
+
b1.length = 10;
|
|
47
|
+
|
|
48
|
+
// Direct access (array-like)
|
|
49
|
+
b1[0] = 72; // 'H' character in ASCII
|
|
50
|
+
|
|
51
|
+
// Free memory
|
|
52
|
+
b1.release();
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## 2. Titanium.Codec
|
|
56
|
+
|
|
57
|
+
The Codec module allows encoding and decoding primitive data (numbers and strings) to/from buffers.
|
|
58
|
+
|
|
59
|
+
### Encoding Numbers
|
|
60
|
+
```javascript
|
|
61
|
+
const buffer = Ti.createBuffer({ length: 8 });
|
|
62
|
+
Ti.Codec.encodeNumber({
|
|
63
|
+
source: 12345,
|
|
64
|
+
dest: buffer,
|
|
65
|
+
type: Ti.Codec.TYPE_INT,
|
|
66
|
+
byteOrder: Ti.Codec.BIG_ENDIAN
|
|
67
|
+
});
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Decoding Strings
|
|
71
|
+
```javascript
|
|
72
|
+
const text = Ti.Codec.decodeString({
|
|
73
|
+
source: buffer,
|
|
74
|
+
charset: Ti.Codec.CHARSET_UTF8
|
|
75
|
+
});
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## 3. Streams
|
|
79
|
+
|
|
80
|
+
Streams allow reading and writing data in a serialized and memory-efficient way.
|
|
81
|
+
|
|
82
|
+
### Stream Types
|
|
83
|
+
1. **BufferStream**: For reading/writing in memory buffers.
|
|
84
|
+
2. **FileStream**: For file operations (more efficient than `file.read()`).
|
|
85
|
+
3. **BlobStream**: Read-only for Blob objects (images, camera).
|
|
86
|
+
|
|
87
|
+
### Example: BufferStream
|
|
88
|
+
```javascript
|
|
89
|
+
const buffer = Ti.createBuffer({ length: 1024 });
|
|
90
|
+
const stream = Ti.Stream.createStream({
|
|
91
|
+
source: buffer,
|
|
92
|
+
mode: Ti.Stream.MODE_WRITE
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
stream.write(Ti.createBuffer({ value: "Stream data" }));
|
|
96
|
+
stream.close();
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Example: FileStream (Chunk-based reading)
|
|
100
|
+
```javascript
|
|
101
|
+
const file = Ti.Filesystem.getFile('large_file.txt');
|
|
102
|
+
const instream = file.open(Ti.Filesystem.MODE_READ);
|
|
103
|
+
const buffer = Ti.createBuffer({ length: 1024 }); // 1KB chunks
|
|
104
|
+
|
|
105
|
+
let bytesRead = 0;
|
|
106
|
+
while ((bytesRead = instream.read(buffer)) > 0) {
|
|
107
|
+
Ti.API.info(`Read ${bytesRead} bytes`);
|
|
108
|
+
// Process buffer...
|
|
109
|
+
}
|
|
110
|
+
instream.close();
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Example: BlobStream (Camera to File)
|
|
114
|
+
```javascript
|
|
115
|
+
Ti.Media.showCamera({
|
|
116
|
+
success: (e) => {
|
|
117
|
+
const instream = Ti.Stream.createStream({
|
|
118
|
+
source: e.media,
|
|
119
|
+
mode: Ti.Stream.MODE_READ
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
const outfile = Ti.Filesystem.getFile(Ti.Filesystem.applicationDataDirectory, 'photo.jpg');
|
|
123
|
+
const outstream = outfile.open(Ti.Filesystem.MODE_WRITE);
|
|
124
|
+
|
|
125
|
+
const buffer = Ti.createBuffer({ length: 4096 });
|
|
126
|
+
let readBytes = 0;
|
|
127
|
+
while ((readBytes = instream.read(buffer)) > 0) {
|
|
128
|
+
outstream.write(buffer, 0, readBytes);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
instream.close();
|
|
132
|
+
outstream.close();
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## 4. Best Practices
|
|
138
|
+
- **Always close streams**: Avoid memory leaks and file locks by calling `.close()`.
|
|
139
|
+
- **Use chunks**: For large files or networking, read in small blocks (e.g., 1KB or 4KB) to avoid saturating RAM.
|
|
140
|
+
- **Buffers vs Blobs**: Buffers are mutable; Blobs are immutable. Convert a Blob to a Buffer if you need to modify bytes.
|
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
# Cross-Platform Development
|
|
2
|
+
|
|
3
|
+
Strategies and techniques for building Titanium apps that work on iOS and Android from a single codebase.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Cross-Platform Development](#cross-platform-development)
|
|
8
|
+
- [Table of Contents](#table-of-contents)
|
|
9
|
+
- [Philosophy](#philosophy)
|
|
10
|
+
- ["Write Once, Adapt Everywhere"](#write-once-adapt-everywhere)
|
|
11
|
+
- [Embrace the Platform](#embrace-the-platform)
|
|
12
|
+
- [Platform Identification](#platform-identification)
|
|
13
|
+
- [Platform Properties](#platform-properties)
|
|
14
|
+
- [Best Practice: Cache Platform Checks](#best-practice-cache-platform-checks)
|
|
15
|
+
- [Anti-Pattern: Don't Assume Binary](#anti-pattern-dont-assume-binary)
|
|
16
|
+
- [Coding Strategies](#coding-strategies)
|
|
17
|
+
- [1. Branching (For Mostly Similar Code)](#1-branching-for-mostly-similar-code)
|
|
18
|
+
- [2. Platform-Specific Files (For Mostly Different Code)](#2-platform-specific-files-for-mostly-different-code)
|
|
19
|
+
- [3. Single Execution Context (Recommended)](#3-single-execution-context-recommended)
|
|
20
|
+
- [Platform-Specific Resources](#platform-specific-resources)
|
|
21
|
+
- [Resource Overrides System](#resource-overrides-system)
|
|
22
|
+
- [Assets (Alloy)](#assets-alloy)
|
|
23
|
+
- [5. Webpack Build Pipeline (TiSDK 9.1.0+)](#5-webpack-build-pipeline-tisdk-910)
|
|
24
|
+
- [`@` Alias](#-alias)
|
|
25
|
+
- [NPM Support](#npm-support)
|
|
26
|
+
- [6. Internationalization (i18n)](#6-internationalization-i18n)
|
|
27
|
+
- [Using Localized Strings](#using-localized-strings)
|
|
28
|
+
- [Date and Currency Formatting](#date-and-currency-formatting)
|
|
29
|
+
- [Testing Localizations](#testing-localizations)
|
|
30
|
+
- [Platform-Specific APIs](#platform-specific-apis)
|
|
31
|
+
- [Example: Platform-Specific Properties](#example-platform-specific-properties)
|
|
32
|
+
- [Common Cross-Platform Patterns](#common-cross-platform-patterns)
|
|
33
|
+
- [Tab Groups](#tab-groups)
|
|
34
|
+
- [Navigation](#navigation)
|
|
35
|
+
- [Platform-Specific Event Handling](#platform-specific-event-handling)
|
|
36
|
+
- [Best Practices](#best-practices)
|
|
37
|
+
- [Resources](#resources)
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Philosophy
|
|
42
|
+
|
|
43
|
+
### "Write Once, Adapt Everywhere"
|
|
44
|
+
|
|
45
|
+
Titanium is **not** "write once, run anywhere." It's "write once, **adapt** everywhere."
|
|
46
|
+
|
|
47
|
+
**What's shared (90-100%):**
|
|
48
|
+
- Business logic
|
|
49
|
+
- Networking code
|
|
50
|
+
- Database operations
|
|
51
|
+
- Event handling
|
|
52
|
+
- Data models
|
|
53
|
+
|
|
54
|
+
**What differs:**
|
|
55
|
+
- UI conventions (tabs position, navigation)
|
|
56
|
+
- Platform-specific features
|
|
57
|
+
- Hardware capabilities
|
|
58
|
+
- User expectations
|
|
59
|
+
|
|
60
|
+
### Embrace the Platform
|
|
61
|
+
|
|
62
|
+
Best-of-breed apps feel **native** on each platform:
|
|
63
|
+
|
|
64
|
+
- **iOS** - Bottom tabs, left navigation buttons, iOS-specific controls
|
|
65
|
+
- **Android** - Top tabs, Menu button (legacy), Action Bar, Material Design
|
|
66
|
+
|
|
67
|
+
**Develop for both platforms from the start** - much more efficient than porting later.
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## Platform Identification
|
|
72
|
+
|
|
73
|
+
### Platform Properties
|
|
74
|
+
|
|
75
|
+
```javascript
|
|
76
|
+
// Platform name
|
|
77
|
+
Ti.Platform.name // "iPhone OS", "android", "mobileweb"
|
|
78
|
+
Ti.Platform.osname // "iphone", "ipad", "android", "mobileweb"
|
|
79
|
+
Ti.Platform.model // "iPhone 15", "Pixel 8", etc.
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Best Practice: Cache Platform Checks
|
|
83
|
+
|
|
84
|
+
```javascript
|
|
85
|
+
// Create aliases - query once, use many times
|
|
86
|
+
const osname = Ti.Platform.osname;
|
|
87
|
+
const isAndroid = (osname === 'android');
|
|
88
|
+
const isIOS = (osname === 'iphone' || osname === 'ipad');
|
|
89
|
+
const isMobileWeb = (osname === 'mobileweb');
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Anti-Pattern: Don't Assume Binary
|
|
93
|
+
|
|
94
|
+
```javascript
|
|
95
|
+
// BAD: Assumes if not Android, then iOS
|
|
96
|
+
if (osname !== 'android') {
|
|
97
|
+
// Wrong! Could be mobile web or future platform
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// GOOD: Explicit checks
|
|
101
|
+
if (isAndroid) {
|
|
102
|
+
// Android code
|
|
103
|
+
} else if (isIOS) {
|
|
104
|
+
// iOS code
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## Coding Strategies
|
|
111
|
+
|
|
112
|
+
### 1. Branching (For Mostly Similar Code)
|
|
113
|
+
|
|
114
|
+
Use when code is 90%+ the same with small differences.
|
|
115
|
+
|
|
116
|
+
```javascript
|
|
117
|
+
const isAndroid = (Ti.Platform.osname === 'android');
|
|
118
|
+
|
|
119
|
+
const win = Ti.UI.createWindow({
|
|
120
|
+
backgroundColor: 'white',
|
|
121
|
+
// Platform-specific property
|
|
122
|
+
softInputMode: isAndroid ? Ti.UI.Android.SOFT_INPUT_ADJUST_PAN : null
|
|
123
|
+
});
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
**Tips:**
|
|
127
|
+
- Cache platform checks to avoid repeated "bridge crossings"
|
|
128
|
+
- Group as much code as possible within branches
|
|
129
|
+
- Defer loading to reduce performance impact
|
|
130
|
+
|
|
131
|
+
### 2. Platform-Specific Files (For Mostly Different Code)
|
|
132
|
+
|
|
133
|
+
Use when code differs significantly between platforms.
|
|
134
|
+
|
|
135
|
+
**Structure:**
|
|
136
|
+
```
|
|
137
|
+
Resources/
|
|
138
|
+
├── ui.js // Common code (optional)
|
|
139
|
+
├── android/
|
|
140
|
+
│ └── ui.js // Android-specific (overrides)
|
|
141
|
+
└── iphone/
|
|
142
|
+
└── ui.js // iOS-specific (overrides)
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
**Usage:**
|
|
146
|
+
```javascript
|
|
147
|
+
// Will automatically include the specific version
|
|
148
|
+
const ui = require('ui');
|
|
149
|
+
// Carga: /android/ui.js en Android, /iphone/ui.js en iOS
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### 3. Single Execution Context (Recommended)
|
|
153
|
+
|
|
154
|
+
**Avoid multiple contexts:**
|
|
155
|
+
```javascript
|
|
156
|
+
// Creates a new context - variables from app.js are not available
|
|
157
|
+
Ti.UI.createWindow({
|
|
158
|
+
url: 'window.js' // DON'T DO THIS
|
|
159
|
+
}).open();
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
**Use instead:**
|
|
163
|
+
```javascript
|
|
164
|
+
// Same context - all variables available
|
|
165
|
+
const win = Ti.UI.createWindow({});
|
|
166
|
+
require('window')(win);
|
|
167
|
+
win.open();
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## Platform-Specific Resources
|
|
173
|
+
|
|
174
|
+
### Resource Overrides System
|
|
175
|
+
|
|
176
|
+
```javascript
|
|
177
|
+
// Automatically uses the platform-specific version
|
|
178
|
+
const image = Ti.UI.createImageView({
|
|
179
|
+
image: '/images/logo.png' // Will choose the correct file
|
|
180
|
+
});
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Assets (Alloy)
|
|
184
|
+
|
|
185
|
+
```
|
|
186
|
+
app/
|
|
187
|
+
├── assets/
|
|
188
|
+
│ └── images/
|
|
189
|
+
│ └── logo.png // Default
|
|
190
|
+
├── assets/
|
|
191
|
+
│ └── android/
|
|
192
|
+
│ └── images/
|
|
193
|
+
│ └── logo.png // Android
|
|
194
|
+
└── assets/
|
|
195
|
+
└── iphone/
|
|
196
|
+
└── images/
|
|
197
|
+
└── logo.png // iOS
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## 5. Webpack Build Pipeline (TiSDK 9.1.0+)
|
|
203
|
+
|
|
204
|
+
Titanium's modern build engine optimizes packaging and allows using NPM libraries natively.
|
|
205
|
+
|
|
206
|
+
### `@` Alias
|
|
207
|
+
Use `@` to reference your code root regardless of the current folder depth.
|
|
208
|
+
```javascript
|
|
209
|
+
import MyModule from '@/utils/myModule'; // Points to app/lib or src
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### NPM Support
|
|
213
|
+
Install any NPM package in the project root and use it directly with `import`.
|
|
214
|
+
|
|
215
|
+
For more details on optimization, diagnostics, and build Web UI, see:
|
|
216
|
+
- [Webpack Build Pipeline](./webpack-build-pipeline.md)
|
|
217
|
+
|
|
218
|
+
## 6. Internationalization (i18n)
|
|
219
|
+
|
|
220
|
+
### Using Localized Strings
|
|
221
|
+
|
|
222
|
+
**Basic usage:**
|
|
223
|
+
```javascript
|
|
224
|
+
// Two equivalent methods
|
|
225
|
+
const str1 = L('welcome_message');
|
|
226
|
+
const str2 = Ti.Locale.getString('welcome_message');
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
**String formatting:**
|
|
230
|
+
```javascript
|
|
231
|
+
// Simple replacement
|
|
232
|
+
const formatted = String.format(L('format_test'), 'Kevin');
|
|
233
|
+
// Result: "Your name is Kevin"
|
|
234
|
+
|
|
235
|
+
// Ordered replacement
|
|
236
|
+
const formatted = String.format(L('ordered'), 'Jeff', 'Kevin');
|
|
237
|
+
// Result: "Hi Jeff, my name is Kevin"
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### Date and Currency Formatting
|
|
241
|
+
|
|
242
|
+
```javascript
|
|
243
|
+
// Date formatting
|
|
244
|
+
const today = new Date();
|
|
245
|
+
const dateStr = String.formatDate(today, 'long');
|
|
246
|
+
const timeStr = String.formatTime(today, 'short');
|
|
247
|
+
|
|
248
|
+
// Currency
|
|
249
|
+
const price = String.formatCurrency(1234.56);
|
|
250
|
+
|
|
251
|
+
// Decimal
|
|
252
|
+
const amount = String.formatDecimal(1234.56);
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
### Testing Localizations
|
|
256
|
+
|
|
257
|
+
**iOS:**
|
|
258
|
+
1. Settings → General → Language & Region
|
|
259
|
+
2. Change iPhone Language
|
|
260
|
+
3. Confirm and restart device
|
|
261
|
+
|
|
262
|
+
**Android:**
|
|
263
|
+
1. Settings → Language & input
|
|
264
|
+
2. Select Language
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
## Platform-Specific APIs
|
|
269
|
+
|
|
270
|
+
### Example: Platform-Specific Properties
|
|
271
|
+
|
|
272
|
+
```javascript
|
|
273
|
+
const win = Ti.UI.createWindow({
|
|
274
|
+
// iOS-specific
|
|
275
|
+
barColor: isIOS ? '#007AFF' : null,
|
|
276
|
+
titlePrompt: isIOS ? 'Title' : null,
|
|
277
|
+
|
|
278
|
+
// Android-specific
|
|
279
|
+
softInputMode: isAndroid ? Ti.UI.Android.SOFT_INPUT_ADJUST_PAN : null,
|
|
280
|
+
exitOnClose: isAndroid ? true : false
|
|
281
|
+
});
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
---
|
|
285
|
+
|
|
286
|
+
## Common Cross-Platform Patterns
|
|
287
|
+
|
|
288
|
+
### Tab Groups
|
|
289
|
+
|
|
290
|
+
```javascript
|
|
291
|
+
const tabGroup = Ti.UI.createTabGroup();
|
|
292
|
+
|
|
293
|
+
const tab1 = Ti.UI.createTab({
|
|
294
|
+
title: 'Tab 1',
|
|
295
|
+
icon: isIOS ? 'tab1.png' : null, // iOS uses icons
|
|
296
|
+
window: win1
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
tabGroup.addTab(tab1);
|
|
300
|
+
tabGroup.open();
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
### Navigation
|
|
304
|
+
|
|
305
|
+
```javascript
|
|
306
|
+
if (isIOS) {
|
|
307
|
+
// iOS: Navigation window with back button
|
|
308
|
+
const nav = Ti.UI.iOS.createNavigationWindow({
|
|
309
|
+
window: win
|
|
310
|
+
});
|
|
311
|
+
nav.open();
|
|
312
|
+
} else if (isAndroid) {
|
|
313
|
+
// Android: Open window, use physical button
|
|
314
|
+
win.open();
|
|
315
|
+
}
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
### Platform-Specific Event Handling
|
|
319
|
+
|
|
320
|
+
```javascript
|
|
321
|
+
if (isAndroid) {
|
|
322
|
+
// Android: Handle physical 'Back' button
|
|
323
|
+
win.addEventListener('androidback', (e) => {
|
|
324
|
+
// Custom behavior
|
|
325
|
+
alert('Back pressed!');
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
---
|
|
331
|
+
|
|
332
|
+
## Best Practices
|
|
333
|
+
|
|
334
|
+
1. **Test early on both platforms** - Don't wait until "porting time"
|
|
335
|
+
2. **Use Alloy framework** - Provides MVC structure and platform abstraction
|
|
336
|
+
3. **Follow platform conventions** - iOS apps should feel like iOS, Android like Android
|
|
337
|
+
4. **Cache platform checks** - Store in variables, don't call `Ti.Platform.osname` repeatedly
|
|
338
|
+
5. **Use CommonJS modules** - Better code organization and reusability
|
|
339
|
+
6. **Leverage resource overrides** - Avoid conditional code for images/assets
|
|
340
|
+
7. **Think cross-platform from design phase** - UI should adapt gracefully
|
|
341
|
+
|
|
342
|
+
---
|
|
343
|
+
|
|
344
|
+
## Resources
|
|
345
|
+
|
|
346
|
+
- **Alloy Framework** - MVC framework for Titanium (see alloy-guides skill)
|
|
347
|
+
- **CommonJS Modules** - Module specification (see coding-strategies above)
|
|
348
|
+
- **Platform API Deep Dives** - iOS and Android platform-specific features
|