mirror of
https://github.com/ish-app/ish.git
synced 2026-05-28 21:10:35 +00:00
Add location tracking device
Supports tracking your location in the background, which has the nice side effect of keeping everything in app running in the background. #249
This commit is contained in:
+7
-1
@@ -9,7 +9,8 @@
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#import "AppDelegate.h"
|
||||
#import "Pasteboard.h"
|
||||
#import "PasteboardDevice.h"
|
||||
#import "LocationDevice.h"
|
||||
#import "TerminalViewController.h"
|
||||
#import "UserPreferences.h"
|
||||
#include "kernel/init.h"
|
||||
@@ -116,6 +117,11 @@ static void ios_handle_die(const char *msg) {
|
||||
return err;
|
||||
}
|
||||
generic_mknod("/dev/clipboard", S_IFCHR|0666, dev_make(DYN_DEV_MAJOR, DEV_CLIPBOARD_MINOR));
|
||||
|
||||
err = dyn_dev_register(&location_dev, DEV_CHAR, DYN_DEV_MAJOR, DEV_LOCATION_MINOR);
|
||||
if (err != 0)
|
||||
return err;
|
||||
generic_mknod("/dev/location", S_IFCHR|0666, dev_make(DYN_DEV_MAJOR, DEV_LOCATION_MINOR));
|
||||
|
||||
do_mount(&procfs, "proc", "/proc", 0);
|
||||
do_mount(&devptsfs, "devpts", "/dev/pts", 0);
|
||||
|
||||
+10
-2
@@ -20,12 +20,16 @@
|
||||
<string>60</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UIBackgroundModes</key>
|
||||
<array>
|
||||
<string>location</string>
|
||||
</array>
|
||||
<key>UIFileSharingEnabled</key>
|
||||
<true/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIMainStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
<key>UIFileSharingEnabled</key>
|
||||
<true/>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
@@ -46,5 +50,9 @@
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
|
||||
<string>A program running in iSH wants to track your location in the background.</string>
|
||||
<key>NSLocationWhenInUseUsageDescription</key>
|
||||
<string>A program running in iSH wants to track your location.</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
//
|
||||
// LocationDevice.h
|
||||
// iSH
|
||||
//
|
||||
// Created by Theodore Dubois on 10/20/19.
|
||||
//
|
||||
|
||||
extern struct dev_ops location_dev;
|
||||
@@ -0,0 +1,174 @@
|
||||
//
|
||||
// LocationDevice.m
|
||||
// iSH
|
||||
//
|
||||
// Created by Theodore Dubois on 10/20/19.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <CoreLocation/CoreLocation.h>
|
||||
#include "kernel/fs.h"
|
||||
#include "fs/dev.h"
|
||||
#include "util/sync.h"
|
||||
|
||||
@interface LocationTracker : NSObject <CLLocationManagerDelegate>
|
||||
|
||||
+ (LocationTracker *)instance;
|
||||
|
||||
@property CLLocationManager *locationManager;
|
||||
@property (nonatomic) CLLocation *latest;
|
||||
@property lock_t lock;
|
||||
@property cond_t updateCond;
|
||||
|
||||
- (int)waitForUpdate;
|
||||
|
||||
@end
|
||||
|
||||
BOOL CLIsAuthorized(CLAuthorizationStatus status) {
|
||||
return status == kCLAuthorizationStatusAuthorizedWhenInUse || status == kCLAuthorizationStatusAuthorizedAlways;
|
||||
}
|
||||
|
||||
@implementation LocationTracker
|
||||
|
||||
+ (LocationTracker *)instance {
|
||||
static __weak LocationTracker *tracker;
|
||||
if (tracker == nil) {
|
||||
__block LocationTracker *newTracker;
|
||||
dispatch_sync(dispatch_get_main_queue(), ^{
|
||||
if (tracker == nil) {
|
||||
newTracker = [LocationTracker new];
|
||||
tracker = newTracker;
|
||||
}
|
||||
});
|
||||
return newTracker;
|
||||
}
|
||||
return tracker;
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
if (self = [super init]) {
|
||||
self.locationManager = [CLLocationManager new];
|
||||
self.locationManager.delegate = self;
|
||||
self.locationManager.allowsBackgroundLocationUpdates = YES;
|
||||
if (CLIsAuthorized([CLLocationManager authorizationStatus])) {
|
||||
[self.locationManager startUpdatingLocation];
|
||||
[self.locationManager requestLocation];
|
||||
} else {
|
||||
[self.locationManager requestAlwaysAuthorization];
|
||||
}
|
||||
|
||||
lock_init(&_lock);
|
||||
cond_init(&_updateCond);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations {
|
||||
lock(&_lock);
|
||||
self.latest = locations.lastObject;
|
||||
notify(&_updateCond);
|
||||
unlock(&_lock);
|
||||
}
|
||||
|
||||
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
|
||||
NSLog(@"location failed %@", error);
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[self.locationManager stopUpdatingLocation];
|
||||
cond_destroy(&_updateCond);
|
||||
}
|
||||
|
||||
- (int)waitForUpdate {
|
||||
lock(&_lock);
|
||||
CLLocation *oldLatest = self.latest;
|
||||
int err = 0;
|
||||
while (self.latest == oldLatest) {
|
||||
err = wait_for(&_updateCond, &_lock, NULL);
|
||||
if (err < 0)
|
||||
break;
|
||||
}
|
||||
unlock(&_lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
|
||||
if (status == kCLAuthorizationStatusAuthorizedAlways || status == kCLAuthorizationStatusAuthorizedWhenInUse) {
|
||||
NSLog(@"got auth, starting updates");
|
||||
[manager startUpdatingLocation];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface LocationFile : NSObject {
|
||||
NSData *buffer;
|
||||
size_t bufferOffset;
|
||||
}
|
||||
|
||||
@property LocationTracker *tracker;
|
||||
|
||||
- (ssize_t)readIntoBuffer:(void *)buf size:(size_t)size;
|
||||
|
||||
@end
|
||||
|
||||
@implementation LocationFile
|
||||
|
||||
- (instancetype)init {
|
||||
if (self = [super init]) {
|
||||
self.tracker = [LocationTracker instance];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (int)waitForUpdate {
|
||||
if (buffer != nil)
|
||||
return 0;
|
||||
int err = [self.tracker waitForUpdate];
|
||||
if (err < 0)
|
||||
return err;
|
||||
CLLocation *location = self.tracker.latest;
|
||||
NSString *output = [NSString stringWithFormat:@"%+f,%+f\n", location.coordinate.latitude, location.coordinate.longitude];
|
||||
buffer = [output dataUsingEncoding:NSUTF8StringEncoding];
|
||||
bufferOffset = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (ssize_t)readIntoBuffer:(void *)buf size:(size_t)size {
|
||||
@synchronized (self) {
|
||||
int err = [self waitForUpdate];
|
||||
if (err < 0)
|
||||
return err;
|
||||
size_t remaining = buffer.length - bufferOffset;
|
||||
if (size > remaining)
|
||||
size = remaining;
|
||||
[buffer getBytes:buf range:NSMakeRange(bufferOffset, size)];
|
||||
bufferOffset += size;
|
||||
if (bufferOffset == buffer.length)
|
||||
buffer = nil;
|
||||
return size;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
static int location_open(int major, int minor, struct fd *fd) {
|
||||
fd->data = (void *) CFBridgingRetain([LocationFile new]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int location_close(struct fd *fd) {
|
||||
CFBridgingRelease(fd->data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t location_read(struct fd *fd, void *buf, size_t size) {
|
||||
LocationFile *file = (__bridge LocationFile *) fd->data;
|
||||
return [file readIntoBuffer:buf size:size];
|
||||
}
|
||||
|
||||
const struct dev_ops location_dev = {
|
||||
.open = location_open,
|
||||
.fd.close = location_close,
|
||||
.fd.read = location_read,
|
||||
};
|
||||
@@ -0,0 +1,2 @@
|
||||
// Pasteboard is implementation of /dev/clipboard device
|
||||
extern struct dev_ops clipboard_dev;
|
||||
@@ -0,0 +1,252 @@
|
||||
#include <string.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
#include "fs/poll.h"
|
||||
#include "fs/dyndev.h"
|
||||
#include "kernel/errno.h"
|
||||
#include "debug.h"
|
||||
|
||||
/**
|
||||
* buffer is dynamically sized buffer of size buffer_cap
|
||||
* All writes go to it, and buffer_len is length of data held in buffer
|
||||
*/
|
||||
|
||||
// Prepare for fd separation
|
||||
#define fd_priv(fd) fd->clipboard
|
||||
typedef struct fd clip_fd;
|
||||
|
||||
#define INITIAL_BUFFER_CAP 1024
|
||||
// 8MB: https://stackoverflow.com/a/3523175
|
||||
#define MAXIMAL_BUFFER_CAP 8*1024*1024
|
||||
|
||||
// If pasteboard contents were changed since file was opened,
|
||||
// all read operations on in return error
|
||||
static int check_read_generation(clip_fd *fd) {
|
||||
UIPasteboard *pb = UIPasteboard.generalPasteboard;
|
||||
|
||||
uint64_t pb_gen = (uint64_t) pb.changeCount;
|
||||
uint64_t fd_gen = fd_priv(fd).generation;
|
||||
|
||||
if (fd_gen == 0 || fd->offset == 0) {
|
||||
fd_priv(fd).generation = pb_gen;
|
||||
} else if (fd_gen != pb_gen) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *get_data(clip_fd *fd, size_t *len) {
|
||||
if (fd_priv(fd).buffer != NULL) {
|
||||
*len = fd_priv(fd).buffer_len;
|
||||
return fd_priv(fd).buffer;
|
||||
}
|
||||
|
||||
if (check_read_generation(fd) != 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NSString __autoreleasing *contents = UIPasteboard.generalPasteboard.string;
|
||||
*len = contents.length;
|
||||
return contents.UTF8String;
|
||||
}
|
||||
|
||||
static int realloc_to_fit(clip_fd* fd, size_t fit_len) {
|
||||
// (Re)allocate buffer if there's not enough space to fit fit_len
|
||||
if (fit_len <= fd_priv(fd).buffer_cap) {
|
||||
return 0;
|
||||
}
|
||||
if (fit_len > MAXIMAL_BUFFER_CAP) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t size = fd_priv(fd).buffer_cap * 2;
|
||||
if (size == 0) {
|
||||
size = INITIAL_BUFFER_CAP;
|
||||
}
|
||||
while (size < fit_len) size *= 2;
|
||||
|
||||
void *new_buf = realloc(fd_priv(fd).buffer, size);
|
||||
if (new_buf == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
fd_priv(fd).buffer = new_buf;
|
||||
fd_priv(fd).buffer_cap = size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// buffer => UIPasteboard
|
||||
static int clipboard_write_sync(clip_fd *fd) {
|
||||
if (fd_priv(fd).buffer == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *data = fd_priv(fd).buffer;
|
||||
size_t len = fd_priv(fd).buffer_len;
|
||||
|
||||
// FIXME(stek29): This logs "Returning local object of class NSString"
|
||||
// and I have no idea why (or how to fix it)
|
||||
UIPasteboard.generalPasteboard.string = [[NSString alloc]
|
||||
initWithBytes:data
|
||||
length:len
|
||||
encoding:NSUTF8StringEncoding];
|
||||
|
||||
// Reset generation since we've just updated UIPasteboard
|
||||
// note: offset doesn't change
|
||||
fd_priv(fd).generation = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// UIPasteboard => buffer, return len
|
||||
static ssize_t clipboard_read_sync(clip_fd *fd) {
|
||||
if (fd_priv(fd).buffer != NULL) {
|
||||
free(fd_priv(fd).buffer);
|
||||
fd_priv(fd).buffer = NULL;
|
||||
fd_priv(fd).buffer_cap = 0;
|
||||
fd_priv(fd).buffer_len = 0;
|
||||
}
|
||||
|
||||
@autoreleasepool {
|
||||
size_t len;
|
||||
const void *data = get_data(fd, &len);
|
||||
|
||||
// Make sure size is still INITIAL_BUFFER_CAP based
|
||||
if (realloc_to_fit(fd, len)) {
|
||||
return _ENOMEM;
|
||||
}
|
||||
|
||||
memcpy(fd_priv(fd).buffer, data, len);
|
||||
fd_priv(fd).buffer_len = len;
|
||||
|
||||
return len;
|
||||
}
|
||||
}
|
||||
|
||||
static int clipboard_poll(clip_fd *fd) {
|
||||
return POLL_READ | POLL_WRITE;
|
||||
}
|
||||
|
||||
static ssize_t clipboard_read(clip_fd *fd, void *buf, size_t bufsize) {
|
||||
@autoreleasepool {
|
||||
size_t length = 0;
|
||||
const char *data = get_data(fd, &length);
|
||||
|
||||
if (data == NULL) {
|
||||
return _EIO;
|
||||
}
|
||||
|
||||
size_t remaining = length - fd->offset;
|
||||
if ((size_t) fd->offset > length)
|
||||
remaining = 0;
|
||||
|
||||
size_t n = bufsize;
|
||||
if (n > remaining)
|
||||
n = remaining;
|
||||
|
||||
if (n != 0) {
|
||||
memcpy(buf, data + fd->offset, n);
|
||||
fd->offset += n;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t clipboard_write(clip_fd *fd, const void *buf, size_t bufsize) {
|
||||
size_t new_len = fd->offset + bufsize;
|
||||
size_t old_len = fd_priv(fd).buffer_len;
|
||||
|
||||
if (old_len > new_len) {
|
||||
new_len = old_len;
|
||||
}
|
||||
|
||||
if (realloc_to_fit(fd, new_len)) {
|
||||
return _ENOMEM;
|
||||
}
|
||||
|
||||
// fill the hole between new offset and old len
|
||||
if (old_len < fd->offset) {
|
||||
memset(fd_priv(fd).buffer + old_len, '\0', fd->offset - old_len);
|
||||
}
|
||||
|
||||
memcpy(fd_priv(fd).buffer + fd->offset, buf, bufsize);
|
||||
fd->offset += bufsize;
|
||||
fd_priv(fd).buffer_len = new_len;
|
||||
|
||||
return bufsize;
|
||||
}
|
||||
|
||||
static off_t_ clipboard_lseek(clip_fd *fd, off_t_ off, int whence) {
|
||||
off_t_ old_off = fd->offset;
|
||||
size_t length = 0;
|
||||
|
||||
if (whence != LSEEK_SET || off != 0) {
|
||||
@autoreleasepool {
|
||||
if (get_data(fd, &length) == NULL) {
|
||||
return _EIO;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (whence) {
|
||||
case LSEEK_SET:
|
||||
fd->offset = off;
|
||||
break;
|
||||
|
||||
case LSEEK_CUR:
|
||||
fd->offset += off;
|
||||
break;
|
||||
|
||||
case LSEEK_END:
|
||||
fd->offset = length + off;
|
||||
break;
|
||||
|
||||
default:
|
||||
return _EINVAL;
|
||||
}
|
||||
|
||||
if (fd->offset < 0) {
|
||||
fd->offset = old_off;
|
||||
return _EINVAL;
|
||||
}
|
||||
|
||||
return fd->offset;
|
||||
}
|
||||
|
||||
static int clipboard_close(clip_fd *fd) {
|
||||
clipboard_write_sync(fd);
|
||||
if (fd_priv(fd).buffer != NULL) {
|
||||
free(fd_priv(fd).buffer);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int clipboard_open(int major, int minor, clip_fd *fd) {
|
||||
// Zero fd_priv data
|
||||
memset(&fd_priv(fd), 0, sizeof(fd_priv(fd)));
|
||||
|
||||
// If O_TRUNC is not set, initialize buffer with current pasteboard contents
|
||||
if (!(fd->flags & O_TRUNC_)) {
|
||||
ssize_t len = clipboard_read_sync(fd);
|
||||
if (len < 0) {
|
||||
return (int) len;
|
||||
}
|
||||
if (fd->flags & O_APPEND_) {
|
||||
fd->offset = (size_t) len;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct dev_ops clipboard_dev = {
|
||||
.open = clipboard_open,
|
||||
.fd.read = clipboard_read,
|
||||
.fd.write = clipboard_write,
|
||||
.fd.lseek = clipboard_lseek,
|
||||
.fd.poll = clipboard_poll,
|
||||
.fd.close = clipboard_close,
|
||||
.fd.fsync = clipboard_write_sync,
|
||||
};
|
||||
@@ -38,5 +38,7 @@
|
||||
|
||||
// /dev/clipboard
|
||||
#define DEV_CLIPBOARD_MINOR 0
|
||||
// /dev/gps
|
||||
#define DEV_LOCATION_MINOR 1
|
||||
|
||||
#endif
|
||||
|
||||
@@ -72,6 +72,9 @@ struct fd {
|
||||
// length of actual data stored in the buffer
|
||||
size_t buffer_len;
|
||||
} clipboard;
|
||||
|
||||
// can fit anything in here
|
||||
void *data;
|
||||
};
|
||||
// fs data
|
||||
union {
|
||||
|
||||
@@ -7,12 +7,14 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
650B337422EA235C00B4C03E /* Pasteboard.m in Sources */ = {isa = PBXBuildFile; fileRef = 650B337322EA235C00B4C03E /* Pasteboard.m */; };
|
||||
650B337422EA235C00B4C03E /* PasteboardDevice.m in Sources */ = {isa = PBXBuildFile; fileRef = 650B337322EA235C00B4C03E /* PasteboardDevice.m */; };
|
||||
8632A7BF219A59FB00F02325 /* UserPreferences.m in Sources */ = {isa = PBXBuildFile; fileRef = 8632A7BE219A59FB00F02325 /* UserPreferences.m */; };
|
||||
9A28E4EA219A8B670073D200 /* AboutAppearanceViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A28E4E9219A8B670073D200 /* AboutAppearanceViewController.m */; };
|
||||
BB0FC5921F980A6C00803272 /* Terminal.m in Sources */ = {isa = PBXBuildFile; fileRef = BB0FC5911F980A6B00803272 /* Terminal.m */; };
|
||||
BB13F7EA200ADCED003D1C4D /* libish.a in Frameworks */ = {isa = PBXBuildFile; fileRef = BB13F7DC200AD81D003D1C4D /* libish.a */; };
|
||||
BB1D9D93234A8FE100F364E8 /* AboutNavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = BB1D9D92234A8FE100F364E8 /* AboutNavigationController.m */; };
|
||||
BB235534235D488500139E00 /* LocationDevice.m in Sources */ = {isa = PBXBuildFile; fileRef = BB235533235D488400139E00 /* LocationDevice.m */; };
|
||||
BB235537235D49B300139E00 /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BB235536235D49B300139E00 /* CoreLocation.framework */; };
|
||||
BB23F58D231E1D1400585522 /* ScrollbarView.m in Sources */ = {isa = PBXBuildFile; fileRef = BB23F58C231E1D1400585522 /* ScrollbarView.m */; };
|
||||
BB2B4DAC231D94C300CB578B /* hterm_all.js in Resources */ = {isa = PBXBuildFile; fileRef = BB2B4DAB231D94C300CB578B /* hterm_all.js */; };
|
||||
BB2B4DAD231D998300CB578B /* term.js in Resources */ = {isa = PBXBuildFile; fileRef = BB4A539C1FAA490C00A72ACE /* term.js */; };
|
||||
@@ -100,8 +102,8 @@
|
||||
650B336822E9F0B500B4C03E /* root.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = root.c; sourceTree = "<group>"; };
|
||||
650B336C22EA052400B4C03E /* dyndev.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dyndev.c; sourceTree = "<group>"; };
|
||||
650B336D22EA052400B4C03E /* dyndev.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dyndev.h; sourceTree = "<group>"; };
|
||||
650B337222EA235C00B4C03E /* Pasteboard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Pasteboard.h; sourceTree = "<group>"; };
|
||||
650B337322EA235C00B4C03E /* Pasteboard.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Pasteboard.m; sourceTree = "<group>"; };
|
||||
650B337222EA235C00B4C03E /* PasteboardDevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PasteboardDevice.h; sourceTree = "<group>"; };
|
||||
650B337322EA235C00B4C03E /* PasteboardDevice.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PasteboardDevice.m; sourceTree = "<group>"; };
|
||||
650B337522EA728B00B4C03E /* devices.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = devices.h; sourceTree = "<group>"; };
|
||||
8632A7BD219A59FB00F02325 /* UserPreferences.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UserPreferences.h; sourceTree = "<group>"; };
|
||||
8632A7BE219A59FB00F02325 /* UserPreferences.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = UserPreferences.m; sourceTree = "<group>"; };
|
||||
@@ -115,6 +117,9 @@
|
||||
BB13F7DC200AD81D003D1C4D /* libish.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libish.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
BB1D9D91234A8FE100F364E8 /* AboutNavigationController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AboutNavigationController.h; sourceTree = "<group>"; };
|
||||
BB1D9D92234A8FE100F364E8 /* AboutNavigationController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AboutNavigationController.m; sourceTree = "<group>"; };
|
||||
BB235533235D488400139E00 /* LocationDevice.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LocationDevice.m; sourceTree = "<group>"; };
|
||||
BB235535235D489400139E00 /* LocationDevice.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LocationDevice.h; sourceTree = "<group>"; };
|
||||
BB235536235D49B300139E00 /* CoreLocation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreLocation.framework; path = System/Library/Frameworks/CoreLocation.framework; sourceTree = SDKROOT; };
|
||||
BB23F58B231E1D1400585522 /* ScrollbarView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ScrollbarView.h; sourceTree = "<group>"; };
|
||||
BB23F58C231E1D1400585522 /* ScrollbarView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ScrollbarView.m; sourceTree = "<group>"; };
|
||||
BB2B4DAB231D94C300CB578B /* hterm_all.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = hterm_all.js; path = libapps/hterm/dist/js/hterm_all.js; sourceTree = "<group>"; };
|
||||
@@ -294,6 +299,7 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
BB235537235D49B300139E00 /* CoreLocation.framework in Frameworks */,
|
||||
BB6DB261216435340047A611 /* libiconv.tbd in Frameworks */,
|
||||
BBFB55662158644C00DFE6DE /* libresolv.tbd in Frameworks */,
|
||||
BB13F7EA200ADCED003D1C4D /* libish.a in Frameworks */,
|
||||
@@ -329,6 +335,17 @@
|
||||
name = Scripts;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
BB235532235D472F00139E00 /* Devices */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
650B337222EA235C00B4C03E /* PasteboardDevice.h */,
|
||||
650B337322EA235C00B4C03E /* PasteboardDevice.m */,
|
||||
BB235535235D489400139E00 /* LocationDevice.h */,
|
||||
BB235533235D488400139E00 /* LocationDevice.m */,
|
||||
);
|
||||
name = Devices;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
BB2D71072354244700A10D1E /* platform */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -407,8 +424,7 @@
|
||||
BB23F58B231E1D1400585522 /* ScrollbarView.h */,
|
||||
BB23F58C231E1D1400585522 /* ScrollbarView.m */,
|
||||
BB4A53991FAA40FD00A72ACE /* terminal */,
|
||||
650B337222EA235C00B4C03E /* Pasteboard.h */,
|
||||
650B337322EA235C00B4C03E /* Pasteboard.m */,
|
||||
BB235532235D472F00139E00 /* Devices */,
|
||||
BB792B591F96D90D00FFB7A4 /* Main.storyboard */,
|
||||
BBFB557321586C7600DFE6DE /* About */,
|
||||
BBFB557221586C6600DFE6DE /* Utilities */,
|
||||
@@ -425,6 +441,7 @@
|
||||
BB792B7D1F96E32B00FFB7A4 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
BB235536235D49B300139E00 /* CoreLocation.framework */,
|
||||
BB6DB260216435330047A611 /* libiconv.tbd */,
|
||||
BBFB55652158644C00DFE6DE /* libresolv.tbd */,
|
||||
);
|
||||
@@ -949,6 +966,7 @@
|
||||
files = (
|
||||
9A28E4EA219A8B670073D200 /* AboutAppearanceViewController.m in Sources */,
|
||||
BB1D9D93234A8FE100F364E8 /* AboutNavigationController.m in Sources */,
|
||||
BB235534235D488500139E00 /* LocationDevice.m in Sources */,
|
||||
BB792B581F96D90D00FFB7A4 /* TerminalViewController.m in Sources */,
|
||||
BB78AB2B1FAD22440013E782 /* TerminalView.m in Sources */,
|
||||
BB23F58D231E1D1400585522 /* ScrollbarView.m in Sources */,
|
||||
@@ -961,7 +979,7 @@
|
||||
BB60F55221573FCA003A4E52 /* BarButton.m in Sources */,
|
||||
BBFB557C215878C600DFE6DE /* UIApplication+OpenURL.m in Sources */,
|
||||
BBFB5579215876CD00DFE6DE /* AboutViewController.m in Sources */,
|
||||
650B337422EA235C00B4C03E /* Pasteboard.m in Sources */,
|
||||
650B337422EA235C00B4C03E /* PasteboardDevice.m in Sources */,
|
||||
BBFB557121586C4800DFE6DE /* UIViewController+Back.m in Sources */,
|
||||
BBFB558021587B6800DFE6DE /* ArrowBarButton.m in Sources */,
|
||||
BB792B551F96D90D00FFB7A4 /* AppDelegate.m in Sources */,
|
||||
|
||||
Reference in New Issue
Block a user