├── Delphi
├── TasksExample
│ ├── Simple Client
│ │ ├── FormSimple.vlb
│ │ ├── SimpleTaskClient.res
│ │ ├── SimpleTaskClient.dpr
│ │ ├── FormSimple.pas
│ │ └── FormSimple.fmx
│ ├── SIMPLETESTDB.IB
│ ├── Simple Server
│ │ ├── SimpleRADServerTasks.res
│ │ ├── SimpleRADServerTasks.dpk
│ │ ├── Unit2.pas
│ │ ├── Unit2.dfm
│ │ └── SimpleRADServerTasks.dproj
│ └── pgTaskExample.groupproj
├── ChangeViews
│ ├── SUB.IB
│ ├── Client
│ │ ├── ChangeViewsEMSThingPoint.dpr
│ │ ├── formMain.pas
│ │ ├── formMain.dfm
│ │ └── ChangeViewsEMSThingPoint.dproj
│ ├── Server
│ │ └── RADServerDemo.dpk
│ ├── ModuleCode
│ │ ├── HighScores.Params.pas
│ │ ├── HighScores.API.dfm
│ │ ├── HighScore.dpk
│ │ ├── ChangeView.DataConnection.dfm
│ │ ├── ChangeView.DataConnection.pas
│ │ ├── HighScores.API.pas
│ │ └── ChangeView.Cache.pas
│ └── ChangeViewsInEMS.groupproj
└── REST.DataUpdater.pas
├── SenchaMail
├── data
│ └── SENCHAMAILSERVER.IB
├── SenchaMail.dpk
├── unitLabels.dfm
├── unitLabels.pas
├── unitData.dfm
└── unitData.pas
├── README.md
└── .gitignore
/Delphi/TasksExample/Simple Client/FormSimple.vlb:
--------------------------------------------------------------------------------
1 | [FDMemTable1]
2 | Visible=False
3 |
4 |
--------------------------------------------------------------------------------
/Delphi/ChangeViews/SUB.IB:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DelphiABall/RADServer/HEAD/Delphi/ChangeViews/SUB.IB
--------------------------------------------------------------------------------
/Delphi/TasksExample/SIMPLETESTDB.IB:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DelphiABall/RADServer/HEAD/Delphi/TasksExample/SIMPLETESTDB.IB
--------------------------------------------------------------------------------
/SenchaMail/data/SENCHAMAILSERVER.IB:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DelphiABall/RADServer/HEAD/SenchaMail/data/SENCHAMAILSERVER.IB
--------------------------------------------------------------------------------
/Delphi/TasksExample/Simple Client/SimpleTaskClient.res:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DelphiABall/RADServer/HEAD/Delphi/TasksExample/Simple Client/SimpleTaskClient.res
--------------------------------------------------------------------------------
/Delphi/TasksExample/Simple Server/SimpleRADServerTasks.res:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DelphiABall/RADServer/HEAD/Delphi/TasksExample/Simple Server/SimpleRADServerTasks.res
--------------------------------------------------------------------------------
/Delphi/TasksExample/Simple Client/SimpleTaskClient.dpr:
--------------------------------------------------------------------------------
1 | program SimpleTaskClient;
2 |
3 | uses
4 | System.StartUpCopy,
5 | FMX.Forms,
6 | FormSimple in 'FormSimple.pas' {Form1},
7 | REST.DataUpdater in '..\..\REST.DataUpdater.pas';
8 |
9 | {$R *.res}
10 |
11 | begin
12 | Application.Initialize;
13 | Application.CreateForm(TForm1, Form1);
14 | Application.Run;
15 | end.
16 |
--------------------------------------------------------------------------------
/Delphi/ChangeViews/Client/ChangeViewsEMSThingPoint.dpr:
--------------------------------------------------------------------------------
1 | program ChangeViewsEMSThingPoint;
2 |
3 | uses
4 | Vcl.Forms,
5 | formMain in 'formMain.pas' {Form1},
6 | HighScores.Params in '..\ModuleCode\HighScores.Params.pas',
7 | HighScores.API in '..\ModuleCode\HighScores.API.pas' {dataHighscoresResource: TDataModule},
8 | ChangeView.DataConnection in '..\ModuleCode\ChangeView.DataConnection.pas' {ChangeViewConnection: TDataModule},
9 | ChangeView.Cache in '..\ModuleCode\ChangeView.Cache.pas';
10 |
11 | {$R *.res}
12 |
13 | begin
14 | Application.Initialize;
15 | Application.MainFormOnTaskbar := True;
16 | Application.CreateForm(TForm1, Form1);
17 | Application.Run;
18 | end.
19 |
--------------------------------------------------------------------------------
/Delphi/ChangeViews/Server/RADServerDemo.dpk:
--------------------------------------------------------------------------------
1 | package RADServerDemo;
2 |
3 | {$R *.res}
4 | {$IFDEF IMPLICITBUILDING This IFDEF should not be used by users}
5 | {$ALIGN 8}
6 | {$ASSERTIONS ON}
7 | {$BOOLEVAL OFF}
8 | {$DEBUGINFO OFF}
9 | {$EXTENDEDSYNTAX ON}
10 | {$IMPORTEDDATA ON}
11 | {$IOCHECKS ON}
12 | {$LOCALSYMBOLS ON}
13 | {$LONGSTRINGS ON}
14 | {$OPENSTRINGS ON}
15 | {$OPTIMIZATION OFF}
16 | {$OVERFLOWCHECKS ON}
17 | {$RANGECHECKS ON}
18 | {$REFERENCEINFO ON}
19 | {$SAFEDIVIDE OFF}
20 | {$STACKFRAMES ON}
21 | {$TYPEDADDRESS OFF}
22 | {$VARSTRINGCHECKS ON}
23 | {$WRITEABLECONST OFF}
24 | {$MINENUMSIZE 1}
25 | {$IMAGEBASE $400000}
26 | {$DEFINE DEBUG}
27 | {$ENDIF IMPLICITBUILDING}
28 | {$RUNONLY}
29 | {$IMPLICITBUILD ON}
30 |
31 | requires
32 | rtl,
33 | emsserverapi;
34 |
35 | end.
36 |
--------------------------------------------------------------------------------
/Delphi/ChangeViews/ModuleCode/HighScores.Params.pas:
--------------------------------------------------------------------------------
1 | unit HighScores.Params;
2 |
3 | interface
4 |
5 | uses
6 | EMS.ResourceAPI, EMS.ResourceTypes, System.SysUtils;
7 |
8 | type
9 | TChangeViewParams = Record
10 | public
11 | DeviceID : string;
12 | ChangeViewName : string;
13 | Constructor Create(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
14 | end;
15 |
16 | implementation
17 |
18 | { TChangeViewParams }
19 |
20 | constructor TChangeViewParams.Create(const AContext: TEndpointContext;
21 | const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
22 | begin
23 | DeviceID := ARequest.Params.Values['deviceid'];
24 | ChangeViewName := 'sub_highscore';
25 |
26 | if Self.DeviceID.IsEmpty then
27 | EEMSHTTPError.RaiseBadRequest('DeviceID Missing');
28 | end;
29 |
30 | end.
31 |
--------------------------------------------------------------------------------
/Delphi/ChangeViews/ModuleCode/HighScores.API.dfm:
--------------------------------------------------------------------------------
1 | object dataHighscoresResource: TdataHighscoresResource
2 | Height = 600
3 | Width = 1200
4 | PixelsPerInch = 192
5 | object FDConnection1: TFDConnection
6 | Params.Strings = (
7 | 'Database=c:\data\sub.ib'
8 | 'User_Name=sysdba'
9 | 'Password=masterkey'
10 | 'DriverID=IB')
11 | LoginPrompt = False
12 | Left = 92
13 | Top = 40
14 | end
15 | object qryHIGHSCORES: TFDQuery
16 | Connection = FDConnection1
17 | SQL.Strings = (
18 | 'select * from HIGHSCORES'
19 | '{if !SORT}order by !SORT{fi}')
20 | Left = 260
21 | Top = 112
22 | MacroData = <
23 | item
24 | Value = Null
25 | Name = 'SORT'
26 | end>
27 | end
28 | object dsrHIGHSCORES: TEMSDataSetResource
29 | AllowedActions = [List, Get, Post, Put, Delete]
30 | DataSet = qryHIGHSCORES
31 | Left = 372
32 | Top = 248
33 | end
34 | end
35 |
--------------------------------------------------------------------------------
/Delphi/TasksExample/Simple Server/SimpleRADServerTasks.dpk:
--------------------------------------------------------------------------------
1 | package SimpleRADServerTasks;
2 |
3 | {$R *.res}
4 | {$IFDEF IMPLICITBUILDING This IFDEF should not be used by users}
5 | {$ALIGN 8}
6 | {$ASSERTIONS ON}
7 | {$BOOLEVAL OFF}
8 | {$DEBUGINFO OFF}
9 | {$EXTENDEDSYNTAX ON}
10 | {$IMPORTEDDATA ON}
11 | {$IOCHECKS ON}
12 | {$LOCALSYMBOLS ON}
13 | {$LONGSTRINGS ON}
14 | {$OPENSTRINGS ON}
15 | {$OPTIMIZATION OFF}
16 | {$OVERFLOWCHECKS ON}
17 | {$RANGECHECKS ON}
18 | {$REFERENCEINFO ON}
19 | {$SAFEDIVIDE OFF}
20 | {$STACKFRAMES ON}
21 | {$TYPEDADDRESS OFF}
22 | {$VARSTRINGCHECKS ON}
23 | {$WRITEABLECONST OFF}
24 | {$MINENUMSIZE 1}
25 | {$IMAGEBASE $400000}
26 | {$DEFINE DEBUG}
27 | {$ENDIF IMPLICITBUILDING}
28 | {$RUNONLY}
29 | {$IMPLICITBUILD ON}
30 |
31 | requires
32 | rtl,
33 | emsserverapi,
34 | dbrtl,
35 | emsserverresource,
36 | FireDACCommonDriver,
37 | FireDACCommon,
38 | FireDAC,
39 | FireDACIBDriver;
40 |
41 | contains
42 | Unit2 in 'Unit2.pas' {DataResource1: TDataModule};
43 |
44 | end.
45 |
46 |
47 |
--------------------------------------------------------------------------------
/SenchaMail/SenchaMail.dpk:
--------------------------------------------------------------------------------
1 | package SenchaMail;
2 |
3 | {$R *.res}
4 | {$IFDEF IMPLICITBUILDING This IFDEF should not be used by users}
5 | {$ALIGN 8}
6 | {$ASSERTIONS ON}
7 | {$BOOLEVAL OFF}
8 | {$DEBUGINFO OFF}
9 | {$EXTENDEDSYNTAX ON}
10 | {$IMPORTEDDATA ON}
11 | {$IOCHECKS ON}
12 | {$LOCALSYMBOLS OFF}
13 | {$LONGSTRINGS ON}
14 | {$OPENSTRINGS ON}
15 | {$OPTIMIZATION ON}
16 | {$OVERFLOWCHECKS OFF}
17 | {$RANGECHECKS OFF}
18 | {$REFERENCEINFO OFF}
19 | {$SAFEDIVIDE OFF}
20 | {$STACKFRAMES OFF}
21 | {$TYPEDADDRESS OFF}
22 | {$VARSTRINGCHECKS ON}
23 | {$WRITEABLECONST OFF}
24 | {$MINENUMSIZE 1}
25 | {$IMAGEBASE $400000}
26 | {$DEFINE RELEASE}
27 | {$ENDIF IMPLICITBUILDING}
28 | {$RUNONLY}
29 | {$IMPLICITBUILD ON}
30 |
31 | requires
32 | rtl,
33 | emsserverapi,
34 | dbrtl,
35 | emsserverresource,
36 | FireDACCommonDriver,
37 | FireDACCommon,
38 | FireDAC,
39 | FireDACIBDriver;
40 |
41 | contains
42 | unitData in 'unitData.pas' {MailResource1: TDataModule},
43 | unitLabels in 'unitLabels.pas' {LabelsResource1: TDataModule};
44 |
45 | end.
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/Delphi/ChangeViews/ModuleCode/HighScore.dpk:
--------------------------------------------------------------------------------
1 | package HighScore;
2 |
3 | {$R *.res}
4 | {$IFDEF IMPLICITBUILDING This IFDEF should not be used by users}
5 | {$ALIGN 8}
6 | {$ASSERTIONS ON}
7 | {$BOOLEVAL OFF}
8 | {$DEBUGINFO OFF}
9 | {$EXTENDEDSYNTAX ON}
10 | {$IMPORTEDDATA ON}
11 | {$IOCHECKS ON}
12 | {$LOCALSYMBOLS ON}
13 | {$LONGSTRINGS ON}
14 | {$OPENSTRINGS ON}
15 | {$OPTIMIZATION OFF}
16 | {$OVERFLOWCHECKS ON}
17 | {$RANGECHECKS ON}
18 | {$REFERENCEINFO ON}
19 | {$SAFEDIVIDE OFF}
20 | {$STACKFRAMES ON}
21 | {$TYPEDADDRESS OFF}
22 | {$VARSTRINGCHECKS ON}
23 | {$WRITEABLECONST OFF}
24 | {$MINENUMSIZE 1}
25 | {$IMAGEBASE $400000}
26 | {$DEFINE DEBUG}
27 | {$ENDIF IMPLICITBUILDING}
28 | {$RUNONLY}
29 | {$IMPLICITBUILD ON}
30 |
31 | requires
32 | rtl,
33 | emsserverapi,
34 | dbrtl,
35 | emsserverresource,
36 | FireDACCommonDriver,
37 | FireDACCommon,
38 | FireDAC,
39 | FireDACIBDriver;
40 |
41 | contains
42 | HighScores.API in 'HighScores.API.pas' {dataHighscoresResource: TDataModule},
43 | ChangeView.DataConnection in 'ChangeView.DataConnection.pas' {ChangeViewConnection: TDataModule},
44 | ChangeView.Cache in 'ChangeView.Cache.pas' {ChangeViewCachce: TDataModule},
45 | HighScores.Params in 'HighScores.Params.pas';
46 |
47 | end.
48 |
--------------------------------------------------------------------------------
/Delphi/TasksExample/Simple Server/Unit2.pas:
--------------------------------------------------------------------------------
1 | unit Unit2;
2 |
3 | // EMS Resource Module
4 |
5 | interface
6 |
7 | uses
8 | System.SysUtils, System.Classes, System.JSON,
9 | EMS.Services, EMS.ResourceAPI, EMS.ResourceTypes, FireDAC.Stan.Intf,
10 | FireDAC.Stan.Option, FireDAC.Stan.Error, FireDAC.UI.Intf, FireDAC.Phys.Intf,
11 | FireDAC.Stan.Def, FireDAC.Stan.Pool, FireDAC.Stan.Async, FireDAC.Phys,
12 | FireDAC.Phys.IB, FireDAC.Phys.IBDef, FireDAC.ConsoleUI.Wait,
13 | FireDAC.Stan.Param, FireDAC.DatS, FireDAC.DApt.Intf, FireDAC.DApt, Data.DB,
14 | EMS.DataSetResource, FireDAC.Comp.DataSet, FireDAC.Comp.Client;
15 |
16 | type
17 | [ResourceName('data')]
18 | TDataResource1 = class(TDataModule)
19 | FDConnection1: TFDConnection;
20 | qryTASKS: TFDQuery;
21 | [ResourceSuffix('TASKS')]
22 | // If using Delphi 11.0, use this workaround to enable POST to work.
23 | // [ResourceSuffix('post', './{dummy_id}')] // added "fake" parameter as work around
24 | dsrTASKS: TEMSDataSetResource;
25 | qryTASKSTASK_ID: TIntegerField;
26 | qryTASKSTASK_NAME: TStringField;
27 | qryTASKSCOMPLETED: TBooleanField;
28 |
29 | published
30 | end;
31 |
32 | implementation
33 |
34 | {%CLASSGROUP 'System.Classes.TPersistent'}
35 |
36 | {$R *.dfm}
37 |
38 | uses System.IOUtils;
39 |
40 | procedure Register;
41 | begin
42 | RegisterResource(TypeInfo(TDataResource1));
43 | end;
44 |
45 | initialization
46 | Register;
47 | end.
48 |
49 |
50 |
--------------------------------------------------------------------------------
/SenchaMail/unitLabels.dfm:
--------------------------------------------------------------------------------
1 | object LabelsResource1: TLabelsResource1
2 | Height = 600
3 | Width = 1200
4 | PixelsPerInch = 192
5 | object FDConnection1: TFDConnection
6 | Params.Strings = (
7 | 'Database=C:\data\SENCHAMAILSERVER.IB'
8 | 'User_Name=SYSDBA'
9 | 'Password=masterkey'
10 | 'Port=3050'
11 | 'InstanceName=instance2'
12 | 'DriverID=IB')
13 | UpdateOptions.AssignedValues = [uvGeneratorName]
14 | UpdateOptions.GeneratorName = 'G_ID'
15 | LoginPrompt = False
16 | Left = 60
17 | Top = 32
18 | end
19 | object qryInsert: TFDQuery
20 | Connection = FDConnection1
21 | SQL.Strings = (
22 | 'INSERT INTO MESSAGE_LABELS'
23 | '(MESSAGE_ID, LABEL_ID)'
24 | 'VALUES'
25 | '(:MESSAGE_ID, :LABEL_ID);')
26 | Left = 224
27 | Top = 192
28 | ParamData = <
29 | item
30 | Name = 'MESSAGE_ID'
31 | ParamType = ptInput
32 | end
33 | item
34 | Name = 'LABEL_ID'
35 | ParamType = ptInput
36 | end>
37 | end
38 | object qryDelete: TFDQuery
39 | Connection = FDConnection1
40 | SQL.Strings = (
41 |
42 | 'DELETE FROM MESSAGE_LABELS WHERE MESSAGE_ID =:MESSAGE_ID AND LAB' +
43 | 'EL_ID = :LABEL_ID')
44 | Left = 384
45 | Top = 192
46 | ParamData = <
47 | item
48 | Name = 'MESSAGE_ID'
49 | ParamType = ptInput
50 | end
51 | item
52 | Name = 'LABEL_ID'
53 | ParamType = ptInput
54 | end>
55 | end
56 | end
57 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # RADServer Samples
2 |
3 | I plan to add a number of RAD Server Examples here.
4 | Many of the previous RAD Server code snippets are linked to blogs on https://delphiaball.co.uk/tag/rad-server/
5 |
6 | ## TRESTRequestDataSetAdapter Example
7 | The TRESTResponseDataSetAdapter can be used converts a JSON array response into a TDataSet.
8 | The TRESTRequestDataSetAdapter works in the opposite direction, by coverting a TDataSet into a Post, Put, or Delete request to update the remote data.
9 | The TaskExample sample includes a RAD Server Package and a Client application (just setup the DB path in the package to run it). You can copy and drop the REST.DataUpdater unit into your own application. REST.DataUpdater extend the FireDAC framework to rapidly post updates back to the server. While its recommended to run each request as it comes in, it also allows changes to cache into memory to bulk update.
10 |
11 | Discover the example on YouTube
12 | https://youtu.be/7O1B9LsYUPE
13 |
14 | ## SenchaMail
15 | The SenchaMail sample example uses the SENCHAMAILSERVER.IB database. (found in the data folder)
16 | This is an InterBase database that stores emails, contacts, and labels that are applied to the email.
17 | To use the sample, either place the database at C:\data\SENCHAMAILSERVER.IB or update the connection path in the FDConnection1 components found in unitLabels and unitData.
18 |
19 | The sample acts as a backend for persisting data from the JavaScript client sample created by Stuart98
20 | https://github.com/Stuart98/ext-mail/
21 |
22 |
--------------------------------------------------------------------------------
/Delphi/TasksExample/Simple Server/Unit2.dfm:
--------------------------------------------------------------------------------
1 | object DataResource1: TDataResource1
2 | Height = 558
3 | Width = 778
4 | PixelsPerInch = 192
5 | object FDConnection1: TFDConnection
6 | Params.Strings = (
7 |
8 | 'Database=C:\Source\git\DelphiABall\RADServer\Delphi\TasksExample' +
9 | '\SIMPLETESTDB.IB'
10 | 'User_Name=sysdba'
11 | 'Password=masterkey'
12 | 'DriverID=IB')
13 | Connected = True
14 | LoginPrompt = False
15 | Left = 94
16 | Top = 24
17 | end
18 | object qryTASKS: TFDQuery
19 | Connection = FDConnection1
20 | UpdateOptions.AssignedValues = [uvGeneratorName]
21 | UpdateOptions.GeneratorName = 'NEWID'
22 | UpdateOptions.AutoIncFields = 'TASK_ID'
23 | SQL.Strings = (
24 | 'select * from TASKS')
25 | Left = 274
26 | Top = 32
27 | object qryTASKSTASK_ID: TIntegerField
28 | FieldName = 'TASK_ID'
29 | Origin = 'TASK_ID'
30 | Required = True
31 | end
32 | object qryTASKSTASK_NAME: TStringField
33 | FieldName = 'TASK_NAME'
34 | Origin = 'TASK_NAME'
35 | Size = 255
36 | end
37 | object qryTASKSCOMPLETED: TBooleanField
38 | FieldName = 'COMPLETED'
39 | Origin = 'COMPLETED'
40 | Required = True
41 | end
42 | end
43 | object dsrTASKS: TEMSDataSetResource
44 | AllowedActions = [List, Get, Post, Put, Delete]
45 | DataSet = qryTASKS
46 | KeyFields = 'TASK_ID'
47 | Options = [roEnableParams, roEnablePaging, roEnableSorting, roReturnNewEntityKey, roReturnNewEntityValue]
48 | Left = 282
49 | Top = 184
50 | end
51 | end
52 |
--------------------------------------------------------------------------------
/Delphi/ChangeViews/ModuleCode/ChangeView.DataConnection.dfm:
--------------------------------------------------------------------------------
1 | object ChangeViewConnection: TChangeViewConnection
2 | Height = 1920
3 | Width = 2560
4 | PixelsPerInch = 192
5 | object FDConnection: TFDConnection
6 | Params.Strings = (
7 | 'Database=c:\data\sub.ib'
8 | 'User_Name=sysdba'
9 | 'Password=masterkey'
10 | 'DriverID=IB')
11 | TxOptions.Isolation = xiSnapshot
12 | TxOptions.AutoStop = False
13 | TxOptions.DisconnectAction = xdRollback
14 | LoginPrompt = False
15 | Transaction = FDTransaction1
16 | Left = 108
17 | Top = 56
18 | end
19 | object qryData: TFDQuery
20 | Connection = FDConnection
21 | Transaction = FDTransaction1
22 | SQL.Strings = (
23 | 'select * from HIGHSCORES'
24 | '{if !SORT}order by !SORT{fi}')
25 | Left = 716
26 | Top = 168
27 | MacroData = <
28 | item
29 | Value = Null
30 | Name = 'SORT'
31 | end>
32 | end
33 | object qryActivateChangeView: TFDQuery
34 | Connection = FDConnection
35 | Transaction = FDTransaction1
36 | SecurityOptions.AllowedCommandKinds = [skExecute, skStartTransaction, skCommit, skRollback, skSet]
37 | SecurityOptions.AllowMultiCommands = False
38 | SQL.Strings = (
39 | 'set subscription !SubscriptionName at !DeviceID active;')
40 | Left = 484
41 | Top = 168
42 | MacroData = <
43 | item
44 | Value = 'sub_highscore'
45 | Name = 'SUBSCRIPTIONNAME'
46 | end
47 | item
48 | Value = 'MyDeviceID'
49 | Name = 'DEVICEID'
50 | DataType = mdString
51 | end>
52 | end
53 | object FDTransaction1: TFDTransaction
54 | Options.Isolation = xiSnapshot
55 | Options.AutoStop = False
56 | Options.DisconnectAction = xdRollback
57 | Connection = FDConnection
58 | Left = 192
59 | Top = 192
60 | end
61 | end
62 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Uncomment these types if you want even more clean repository. But be careful.
2 | # It can make harm to an existing project source. Read explanations below.
3 | #
4 | # Resource files are binaries containing manifest, project icon and version info.
5 | # They can not be viewed as text or compared by diff-tools. Consider replacing them with .rc files.
6 | #*.res
7 | #
8 | # Type library file (binary). In old Delphi versions it should be stored.
9 | # Since Delphi 2009 it is produced from .ridl file and can safely be ignored.
10 | #*.tlb
11 | #
12 | # Diagram Portfolio file. Used by the diagram editor up to Delphi 7.
13 | # Uncomment this if you are not using diagrams or use newer Delphi version.
14 | #*.ddp
15 | #
16 | # Visual LiveBindings file. Added in Delphi XE2.
17 | # Uncomment this if you are not using LiveBindings Designer.
18 | #*.vlb
19 | #
20 | # Deployment Manager configuration file for your project. Added in Delphi XE2.
21 | # Uncomment this if it is not mobile development and you do not use remote debug feature.
22 | #*.deployproj
23 | #
24 | # C++ object files produced when C/C++ Output file generation is configured.
25 | # Uncomment this if you are not using external objects (zlib library for example).
26 | #*.obj
27 | #
28 |
29 | # Delphi compiler-generated binaries (safe to delete)
30 | *.exe
31 | *.dll
32 | *.bpl
33 | *.bpi
34 | *.dcp
35 | *.so
36 | *.apk
37 | *.drc
38 | *.map
39 | *.dres
40 | *.rsm
41 | *.tds
42 | *.dcu
43 | *.lib
44 | *.a
45 | *.o
46 | *.ocx
47 |
48 | # Delphi autogenerated files (duplicated info)
49 | *.cfg
50 | *.hpp
51 | *Resource.rc
52 |
53 | # Delphi local files (user-specific info)
54 | *.local
55 | *.identcache
56 | *.projdata
57 | *.tvsconfig
58 | *.dsk
59 |
60 | # Delphi history and backups
61 | __history/
62 | __recovery/
63 | *.~*
64 |
65 | # Castalia statistics file (since XE7 Castalia is distributed with Delphi)
66 | *.stat
67 |
68 | # Boss dependency manager vendor folder https://github.com/HashLoad/boss
69 | modules/
70 | Delphi/ChangeViews/Client/ChangeViewsEMSThingPoint.res
71 | *.res
72 |
--------------------------------------------------------------------------------
/Delphi/TasksExample/pgTaskExample.groupproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | {0E821AB1-738E-4C39-9153-B88AAF8875A4}
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | Default.Personality.12
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 |
--------------------------------------------------------------------------------
/Delphi/ChangeViews/ChangeViewsInEMS.groupproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | {FE7D3E9E-E4DA-4092-9D6E-4CC5FA4418C0}
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | Default.Personality.12
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 |
--------------------------------------------------------------------------------
/Delphi/ChangeViews/Client/formMain.pas:
--------------------------------------------------------------------------------
1 | unit formMain;
2 |
3 | interface
4 |
5 | uses
6 | Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
7 | Vcl.Controls, Vcl.Forms, Vcl.Dialogs, System.JSON, REST.Backend.EMSServices,
8 | EMSHosting.ExtensionsServices, EMSHosting.EdgeHTTPListener,
9 | REST.Backend.EMSProvider, REST.Backend.Providers, EMSHosting.EdgeService,
10 | Vcl.StdCtrls, ChangeView.Cache, FireDAC.UI.Intf, FireDAC.VCLUI.Wait,
11 | FireDAC.Stan.Intf, FireDAC.Comp.UI, Vcl.ExtCtrls, Vcl.Samples.Spin;
12 |
13 | type
14 | TForm1 = class(TForm)
15 | Button1: TButton;
16 | EMSEdgeService1: TEMSEdgeService;
17 | EMSProvider1: TEMSProvider;
18 | FDGUIxWaitCursor1: TFDGUIxWaitCursor;
19 | MemoStatus: TMemo;
20 | Panel1: TPanel;
21 | Label1: TLabel;
22 | TimerStatsUpdate: TTimer;
23 | TimerSweep: TTimer;
24 | btnSweep: TButton;
25 | seLifeSpanSeconds: TSpinEdit;
26 | Label2: TLabel;
27 | procedure Button1Click(Sender: TObject);
28 | procedure FormCreate(Sender: TObject);
29 | procedure FormClose(Sender: TObject; var Action: TCloseAction);
30 | procedure btnSweepClick(Sender: TObject);
31 | procedure TimerSweepTimer(Sender: TObject);
32 | procedure TimerStatsUpdateTimer(Sender: TObject);
33 | private
34 | { Private declarations }
35 | public
36 | { Public declarations }
37 | end;
38 |
39 | var
40 | Form1: TForm1;
41 |
42 | implementation
43 |
44 | {$R *.dfm}
45 |
46 | procedure TForm1.btnSweepClick(Sender: TObject);
47 | begin
48 | TimerSweep.Enabled := not TimerSweep.Enabled;
49 | btnSweep.Caption := 'Sweep Active = '+ BoolToStr(TimerSweep.Enabled, True);
50 | end;
51 |
52 | procedure TForm1.Button1Click(Sender: TObject);
53 | begin
54 | EMSEdgeService1.Active := not EMSEdgeService1.Active;
55 | Button1.Caption := 'Active = '+ BoolToStr(EMSEdgeService1.Active, True);
56 | end;
57 |
58 | procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
59 | begin
60 | if EMSEdgeService1.Active then
61 | EMSEdgeService1.Active := False;
62 | end;
63 |
64 | procedure TForm1.FormCreate(Sender: TObject);
65 | begin
66 | Button1.Caption := 'Active = '+ BoolToStr(EMSEdgeService1.Active, True);
67 | end;
68 |
69 | procedure TForm1.TimerStatsUpdateTimer(Sender: TObject);
70 | begin
71 | ChangeViewSessions.GetStats(MemoStatus.Lines);
72 | end;
73 |
74 | procedure TForm1.TimerSweepTimer(Sender: TObject);
75 | begin
76 | TimerSweep.Enabled := False;
77 | try
78 | // Removes Sessions that have passed their allowed inactive time.
79 | ChangeViewSessions.Sweep(seLifeSpanSeconds.Value);
80 | finally
81 | TimerSweep.Enabled := True;
82 | end;
83 | end;
84 |
85 | end.
86 |
--------------------------------------------------------------------------------
/Delphi/TasksExample/Simple Client/FormSimple.pas:
--------------------------------------------------------------------------------
1 | unit FormSimple;
2 |
3 | interface
4 |
5 | uses
6 | System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
7 | FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, REST.Types,
8 | FireDAC.Stan.Intf, FireDAC.Stan.Option, FireDAC.Stan.Param,
9 | FireDAC.Stan.Error, FireDAC.DatS, FireDAC.Phys.Intf, FireDAC.DApt.Intf,
10 | System.Rtti, FMX.Grid.Style, Data.Bind.EngExt, Fmx.Bind.DBEngExt,
11 | Fmx.Bind.Grid, System.Bindings.Outputs, Fmx.Bind.Editors, Data.Bind.Controls,
12 | FMX.Layouts, Fmx.Bind.Navigator, Data.Bind.Components, Data.Bind.Grid,
13 | Data.Bind.DBScope, FMX.Controls.Presentation, FMX.ScrollBox, FMX.Grid,
14 | Data.DB, FireDAC.Comp.DataSet, FireDAC.Comp.Client, REST.Response.Adapter,
15 | REST.Client, Data.Bind.ObjectScope, FMX.StdCtrls, FMX.Memo.Types, FMX.Memo,
16 | FMX.TabControl, FMX.Edit;
17 |
18 | type
19 | TForm1 = class(TForm)
20 | BindNavigator1: TBindNavigator;
21 | Layout1: TLayout;
22 | Button1: TButton;
23 | Button2: TButton;
24 | StringGrid1: TStringGrid;
25 | BindingsList1: TBindingsList;
26 | RESTClient1: TRESTClient;
27 | RESTRequestGet: TRESTRequest;
28 | RESTResponseGet: TRESTResponse;
29 | RESTResponseDataSetAdapterGet: TRESTResponseDataSetAdapter;
30 | FDMemTable1: TFDMemTable;
31 | BindSourceDB2: TBindSourceDB;
32 | LinkGridToDataSourceBindSourceDB2: TLinkGridToDataSource;
33 | Memo1: TMemo;
34 | TabControl1: TTabControl;
35 | TabItem1: TTabItem;
36 | TabItem2: TTabItem;
37 | Label1: TLabel;
38 | Label2: TLabel;
39 | MemoPostBody: TMemo;
40 | Button3: TButton;
41 | procedure Button1Click(Sender: TObject);
42 | procedure Button2Click(Sender: TObject);
43 | procedure Button3Click(Sender: TObject);
44 | private
45 | { Private declarations }
46 | public
47 | { Public declarations }
48 | end;
49 |
50 | var
51 | Form1: TForm1;
52 |
53 | implementation
54 |
55 | {$R *.fmx}
56 | uses REST.DataUpdater;
57 |
58 | procedure TForm1.Button1Click(Sender: TObject);
59 | begin
60 | RESTRequestGet.Execute;
61 | FDMemTable1.CachedUpdates := True;
62 | end;
63 |
64 | procedure TForm1.Button2Click(Sender: TObject);
65 | begin
66 | var Updater := TRestDataSetUpdater.Create(Self,RESTClient1, 'data/tasks/', 'TASK_ID', FDMemTable1);
67 | try
68 | // Uncomment For RAD Studio / Delphi 11.0 as you need to have a dummy param to make the post work. (known issue fixed in 11.1)
69 | // Updater.ResourcePost := Updater.ResourcePost+'/-1'; // Dummy ID for tempory workaround
70 | Updater.ApplyRemoteUpdates(True);
71 | Memo1.Lines.Text := Updater.ErrorLog.Text;
72 | finally
73 | Updater.Free;
74 | end;
75 |
76 | end;
77 |
78 | procedure TForm1.Button3Click(Sender: TObject);
79 | begin
80 | ShowMessage(FDMemTable1.ChangeCount.ToString);
81 | end;
82 |
83 | end.
84 |
--------------------------------------------------------------------------------
/Delphi/ChangeViews/ModuleCode/ChangeView.DataConnection.pas:
--------------------------------------------------------------------------------
1 | unit ChangeView.DataConnection;
2 |
3 | interface
4 |
5 | uses
6 | System.SysUtils, System.Classes, FireDAC.Stan.Intf, FireDAC.Stan.Option,
7 | FireDAC.Stan.Error, FireDAC.UI.Intf, FireDAC.Phys.Intf, FireDAC.Stan.Def,
8 | FireDAC.Stan.Pool, FireDAC.Stan.Async, FireDAC.Phys, FireDAC.Phys.IB,
9 | FireDAC.Phys.IBDef, FireDAC.ConsoleUI.Wait, FireDAC.Stan.Param, FireDAC.DatS,
10 | FireDAC.DApt.Intf, FireDAC.DApt, Data.DB, FireDAC.Comp.DataSet,
11 | FireDAC.Comp.Client;
12 |
13 | type
14 | TChangeViewConnection = class(TDataModule)
15 | FDConnection: TFDConnection;
16 | qryData: TFDQuery;
17 | qryActivateChangeView: TFDQuery;
18 | FDTransaction1: TFDTransaction;
19 | private
20 | FLastCalled : TDateTime;
21 | function GetDeviceID: string;
22 | function GetSubscriptionName: string;
23 |
24 | { Private declarations }
25 | public
26 | { Public declarations }
27 | constructor Create(AOwner : TComponent; Const ADeviceID, ASubscription : String);
28 | destructor Destroy; override;
29 |
30 | procedure Activate;
31 |
32 | procedure CommitChangeView;
33 | procedure RollBackChangeView;
34 | // Updates the date time for a last made change
35 | procedure MarkAsActive;
36 |
37 | property DeviceID : string read GetDeviceID;
38 | property SubscriptionName : string read GetSubscriptionName;
39 | property LatestActivity : TDateTime read FLastCalled;
40 | end;
41 |
42 | implementation
43 |
44 | {%CLASSGROUP 'System.Classes.TPersistent'}
45 |
46 | {$R *.dfm}
47 |
48 |
49 | procedure TChangeViewConnection.Activate;
50 | begin
51 | if not FDConnection.Connected then
52 | FDConnection.Connected := True;
53 |
54 | if not FDConnection.Transaction.Active then
55 | FDConnection.StartTransaction;
56 |
57 | qryActivateChangeView.ExecSQL;
58 |
59 | MarkAsActive;
60 | end;
61 |
62 | procedure TChangeViewConnection.CommitChangeView;
63 | begin
64 | if FDConnection.Transaction.Active then
65 | FDConnection.Commit;
66 |
67 | MarkAsActive;
68 | end;
69 |
70 | { TdataHighScoreConnection }
71 |
72 | constructor TChangeViewConnection.Create(AOwner: TComponent; const ADeviceID, ASubscription: String);
73 | begin
74 | Assert(ADeviceID > '','Invalid DeviceID');
75 | Assert(ASubscription > '','Invalid Subscription');
76 |
77 | inherited Create(AOwner);
78 |
79 | qryActivateChangeView.MacroByName('SubscriptionName').AsString := ASubscription; //'sub_highscore';
80 | qryActivateChangeView.MacroByName('DeviceID').AsString := ADeviceID;
81 |
82 | MarkAsActive;
83 | end;
84 |
85 | destructor TChangeViewConnection.Destroy;
86 | begin
87 | if FDConnection.Transaction.Active then
88 | RollBackChangeView;
89 | inherited;
90 | end;
91 |
92 | function TChangeViewConnection.GetDeviceID: string;
93 | begin
94 | Result := qryActivateChangeView.MacroByName('DeviceID').AsString;
95 | end;
96 |
97 | procedure TChangeViewConnection.MarkAsActive;
98 | begin
99 | FLastCalled := Now;
100 | end;
101 |
102 | procedure TChangeViewConnection.RollBackChangeView;
103 | begin
104 | if FDConnection.Transaction.Active then
105 | FDConnection.Rollback;
106 |
107 | MarkAsActive;
108 | end;
109 |
110 | function TChangeViewConnection.GetSubscriptionName : string;
111 | begin
112 | Result := qryActivateChangeView.MacroByName('SubscriptionName').AsString;
113 | end;
114 |
115 | end.
116 |
--------------------------------------------------------------------------------
/Delphi/ChangeViews/Client/formMain.dfm:
--------------------------------------------------------------------------------
1 | object Form1: TForm1
2 | Left = 0
3 | Top = 0
4 | Margins.Left = 6
5 | Margins.Top = 6
6 | Margins.Right = 6
7 | Margins.Bottom = 6
8 | Caption = 'Form1'
9 | ClientHeight = 943
10 | ClientWidth = 1274
11 | Color = clBtnFace
12 | Font.Charset = DEFAULT_CHARSET
13 | Font.Color = clWindowText
14 | Font.Height = -24
15 | Font.Name = 'Segoe UI'
16 | Font.Style = []
17 | OnClose = FormClose
18 | OnCreate = FormCreate
19 | PixelsPerInch = 192
20 | DesignSize = (
21 | 1274
22 | 943)
23 | TextHeight = 32
24 | object Label1: TLabel
25 | Left = 0
26 | Top = 145
27 | Width = 1274
28 | Height = 32
29 | Margins.Left = 6
30 | Margins.Top = 6
31 | Margins.Right = 6
32 | Margins.Bottom = 6
33 | Align = alTop
34 | Caption = 'Stats'
35 | ExplicitWidth = 50
36 | end
37 | object Label2: TLabel
38 | Left = 24
39 | Top = 628
40 | Width = 295
41 | Height = 32
42 | Margins.Left = 6
43 | Margins.Top = 6
44 | Margins.Right = 6
45 | Margins.Bottom = 6
46 | Caption = 'Sessions Lifespan (Seconds)'
47 | end
48 | object MemoStatus: TMemo
49 | Left = 0
50 | Top = 177
51 | Width = 1274
52 | Height = 376
53 | Margins.Left = 6
54 | Margins.Top = 6
55 | Margins.Right = 6
56 | Margins.Bottom = 6
57 | Align = alTop
58 | Lines.Strings = (
59 | 'MemoStatus')
60 | TabOrder = 0
61 | end
62 | object Panel1: TPanel
63 | Left = 0
64 | Top = 0
65 | Width = 1274
66 | Height = 145
67 | Margins.Left = 6
68 | Margins.Top = 6
69 | Margins.Right = 6
70 | Margins.Bottom = 6
71 | Align = alTop
72 | BevelOuter = bvNone
73 | TabOrder = 1
74 | object Button1: TButton
75 | Left = 24
76 | Top = 33
77 | Width = 233
78 | Height = 81
79 | Caption = 'Button1'
80 | TabOrder = 0
81 | OnClick = Button1Click
82 | end
83 | end
84 | object seLifeSpanSeconds: TSpinEdit
85 | Left = 416
86 | Top = 625
87 | Width = 185
88 | Height = 43
89 | Margins.Left = 6
90 | Margins.Top = 6
91 | Margins.Right = 6
92 | Margins.Bottom = 6
93 | MaxValue = 3600
94 | MinValue = 5
95 | TabOrder = 2
96 | Value = 60
97 | end
98 | object btnSweep: TButton
99 | Left = 24
100 | Top = 688
101 | Width = 577
102 | Height = 95
103 | Margins.Left = 6
104 | Margins.Top = 6
105 | Margins.Right = 6
106 | Margins.Bottom = 6
107 | Anchors = [akTop, akRight]
108 | Caption = 'Sweep'
109 | TabOrder = 3
110 | OnClick = btnSweepClick
111 | end
112 | object EMSEdgeService1: TEMSEdgeService
113 | ModuleName = 'ChangeViewsDemo'
114 | ModuleVersion = '1'
115 | Provider = EMSProvider1
116 | ListenerProtocol = 'http'
117 | ListenerService.Port = 8888
118 | ListenerService.Host = 'localhost'
119 | Left = 1000
120 | Top = 304
121 | end
122 | object EMSProvider1: TEMSProvider
123 | ApiVersion = '2'
124 | URLHost = 'localhost'
125 | URLPort = 8080
126 | Left = 832
127 | Top = 280
128 | end
129 | object FDGUIxWaitCursor1: TFDGUIxWaitCursor
130 | Provider = 'Forms'
131 | ScreenCursor = gcrHourGlass
132 | Left = 688
133 | Top = 552
134 | end
135 | object TimerStatsUpdate: TTimer
136 | OnTimer = TimerStatsUpdateTimer
137 | Left = 848
138 | Top = 56
139 | end
140 | object TimerSweep: TTimer
141 | OnTimer = TimerSweepTimer
142 | Left = 1136
143 | Top = 72
144 | end
145 | end
146 |
--------------------------------------------------------------------------------
/SenchaMail/unitLabels.pas:
--------------------------------------------------------------------------------
1 | unit unitLabels;
2 |
3 | // EMS Resource Module
4 |
5 | interface
6 |
7 | uses
8 | System.SysUtils, System.Classes, System.JSON,
9 | EMS.Services, EMS.ResourceAPI, EMS.ResourceTypes, FireDAC.Stan.Intf,
10 | FireDAC.Stan.Option, FireDAC.Stan.Error, FireDAC.UI.Intf, FireDAC.Phys.Intf,
11 | FireDAC.Stan.Def, FireDAC.Stan.Pool, FireDAC.Stan.Async, FireDAC.Phys,
12 | FireDAC.Phys.IB, FireDAC.Phys.IBDef, FireDAC.ConsoleUI.Wait, Data.DB,
13 | FireDAC.Comp.Client, FireDAC.Stan.Param, FireDAC.DatS, FireDAC.DApt.Intf,
14 | FireDAC.DApt, FireDAC.Comp.DataSet;
15 |
16 | type
17 | [ResourceName('labels')]
18 | TLabelsResource1 = class(TDataModule)
19 | FDConnection1: TFDConnection;
20 | qryInsert: TFDQuery;
21 | qryDelete: TFDQuery;
22 | published
23 |
24 | [EndPointRequestSummary('Tests', 'PostItem', 'Creates new item', '', 'application/json')]
25 | [EndPointRequestParameter(TAPIDocParameter.TParameterIn.Body, 'body', 'A new item content', true, TAPIDoc.TPrimitiveType.spObject,
26 | TAPIDoc.TPrimitiveFormat.None, TAPIDoc.TPrimitiveType.spObject, '', '')]
27 | [EndPointResponseDetails(200, 'Ok', TAPIDoc.TPrimitiveType.spNull, TAPIDoc.TPrimitiveFormat.None, '', '')]
28 | [EndPointResponseDetails(409, 'Item Exist', TAPIDoc.TPrimitiveType.spNull, TAPIDoc.TPrimitiveFormat.None, '', '')]
29 | [ResourceSuffix('{messageid}/{labelid}')]
30 | procedure Post(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
31 |
32 | [EndPointRequestSummary('Tests', 'DeleteItem', 'Deletes item with specified ID', '', '')]
33 | [EndPointRequestParameter(TAPIDocParameter.TParameterIn.Path, 'item', 'A item ID', true, TAPIDoc.TPrimitiveType.spString,
34 | TAPIDoc.TPrimitiveFormat.None, TAPIDoc.TPrimitiveType.spString, '', '')]
35 | [EndPointResponseDetails(200, 'Ok', TAPIDoc.TPrimitiveType.spNull, TAPIDoc.TPrimitiveFormat.None, '', '')]
36 | [EndPointResponseDetails(404, 'Not Found', TAPIDoc.TPrimitiveType.spNull, TAPIDoc.TPrimitiveFormat.None, '', '')]
37 | [ResourceSuffix('{messageid}/{labelid}')]
38 | procedure DeleteItem(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
39 | end;
40 |
41 | implementation
42 |
43 | {%CLASSGROUP 'System.Classes.TPersistent'}
44 |
45 | {$R *.dfm}
46 |
47 | procedure TLabelsResource1.Post(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
48 | var
49 | FMessageID, FLabelID: string;
50 | begin
51 | FLabelID := ARequest.Params.Values['labelid'];
52 | FMessageID := ARequest.Params.Values['messageid'];
53 |
54 | if StrToIntDef(FMessageID,-1) < 0 then
55 | AResponse.RaiseNotFound('Invalid Message ID');
56 | if StrToIntDef(FLabelID,-1) < 0 then
57 | AResponse.RaiseNotFound('Invalid Label ID');
58 |
59 | qryInsert.ParamByName('MESSAGE_ID').AsString := FMessageID;
60 | qryInsert.ParamByName('LABEL_ID').AsString := FLabelID;
61 | try
62 | qryInsert.ExecSQL;
63 | except
64 | on e:Exception do
65 | AResponse.RaiseDuplicate('Duplicate message label');
66 | end;
67 |
68 | end;
69 |
70 | procedure TLabelsResource1.DeleteItem(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
71 | var
72 | FMessageID, FLabelID: string;
73 | begin
74 | FMessageID := ARequest.Params.Values['messageid'];
75 | FLabelID := ARequest.Params.Values['labelid'];
76 |
77 | if StrToIntDef(FMessageID,-1) < 0 then
78 | AResponse.RaiseNotFound('Invalid Message ID');
79 | if StrToIntDef(FLabelID,-1) < 0 then
80 | AResponse.RaiseNotFound('Invalid Label ID');
81 |
82 | qryDelete.ParamByName('MESSAGE_ID').AsString := FMessageID;
83 | qryDelete.ParamByName('LABEL_ID').AsString := FLabelID;
84 |
85 | try
86 | qryDelete.ExecSQL;
87 | except
88 | on e:Exception do
89 | AResponse.RaiseBadRequest('Invalid Request',e.message);
90 | end;
91 |
92 | end;
93 |
94 | procedure Register;
95 | begin
96 | RegisterResource(TypeInfo(TLabelsResource1));
97 | end;
98 |
99 | initialization
100 | Register;
101 | end.
102 |
103 |
104 |
--------------------------------------------------------------------------------
/SenchaMail/unitData.dfm:
--------------------------------------------------------------------------------
1 | object MailResource1: TMailResource1
2 | Height = 514
3 | Width = 1176
4 | PixelsPerInch = 192
5 | object FDConnection1: TFDConnection
6 | Params.Strings = (
7 | 'Database=C:\data\SENCHAMAILSERVER.IB'
8 | 'User_Name=SYSDBA'
9 | 'Password=masterkey'
10 | 'Port=3050'
11 | 'InstanceName=instance2'
12 | 'DriverID=IB')
13 | UpdateOptions.AssignedValues = [uvGeneratorName]
14 | UpdateOptions.GeneratorName = 'G_ID'
15 | LoginPrompt = False
16 | Left = 60
17 | Top = 32
18 | end
19 | object qryCONTACTS: TFDQuery
20 | Connection = FDConnection1
21 | UpdateOptions.KeyFields = 'ID'
22 | UpdateOptions.AutoIncFields = 'ID'
23 | SQL.Strings = (
24 | 'select * from CONTACTS')
25 | Left = 260
26 | Top = 32
27 | object qryCONTACTSID: TFDAutoIncField
28 | FieldName = 'ID'
29 | Origin = 'ID'
30 | ProviderFlags = [pfInUpdate, pfInWhere, pfInKey]
31 | IdentityInsert = True
32 | end
33 | object qryCONTACTSFIRST_NAME: TStringField
34 | FieldName = 'FIRST_NAME'
35 | Origin = 'FIRST_NAME'
36 | Size = 50
37 | end
38 | object qryCONTACTSLAST_NAME: TStringField
39 | FieldName = 'LAST_NAME'
40 | Origin = 'LAST_NAME'
41 | Size = 50
42 | end
43 | object qryCONTACTSEMAIL: TStringField
44 | FieldName = 'EMAIL'
45 | Origin = 'EMAIL'
46 | Size = 320
47 | end
48 | end
49 | object dsrCONTACTS: TEMSDataSetResource
50 | AllowedActions = [List, Get, Post, Put, Delete]
51 | DataSet = qryCONTACTS
52 | KeyFields = 'ID'
53 | PageSize = 20
54 | Left = 260
55 | Top = 144
56 | end
57 | object qryLABELS: TFDQuery
58 | Connection = FDConnection1
59 | UpdateOptions.KeyFields = 'ID'
60 | UpdateOptions.AutoIncFields = 'ID'
61 | SQL.Strings = (
62 | 'select * from LABELS')
63 | Left = 460
64 | Top = 32
65 | object qryLABELSID: TIntegerField
66 | AutoGenerateValue = arAutoInc
67 | FieldName = 'ID'
68 | Origin = 'ID'
69 | ProviderFlags = [pfInUpdate, pfInWhere, pfInKey]
70 | Required = True
71 | end
72 | object qryLABELSPARENT_ID: TIntegerField
73 | FieldName = 'PARENT_ID'
74 | Origin = 'PARENT_ID'
75 | end
76 | object qryLABELSNAME: TStringField
77 | FieldName = 'NAME'
78 | Origin = 'NAME'
79 | Required = True
80 | Size = 50
81 | end
82 | object qryLABELSLEAF: TBooleanField
83 | FieldName = 'LEAF'
84 | Origin = 'LEAF'
85 | Required = True
86 | end
87 | object qryLABELSEXPANDED: TBooleanField
88 | FieldName = 'EXPANDED'
89 | Origin = 'EXPANDED'
90 | Required = True
91 | end
92 | end
93 | object dsrLABELS: TEMSDataSetResource
94 | AllowedActions = [List, Get, Post, Put, Delete]
95 | DataSet = qryLABELS
96 | KeyFields = 'ID'
97 | Left = 460
98 | Top = 144
99 | end
100 | object qryMESSAGES: TFDQuery
101 | Connection = FDConnection1
102 | UpdateOptions.AssignedValues = [uvGeneratorName]
103 | UpdateOptions.GeneratorName = 'G_ID'
104 | UpdateOptions.KeyFields = 'ID'
105 | UpdateOptions.AutoIncFields = 'ID'
106 | SQL.Strings = (
107 | 'select * from MESSAGES')
108 | Left = 660
109 | Top = 32
110 | object qryMESSAGESID: TIntegerField
111 | FieldName = 'ID'
112 | Origin = 'ID'
113 | ProviderFlags = [pfInUpdate, pfInWhere, pfInKey]
114 | Required = True
115 | end
116 | object qryMESSAGESFIRST_NAME: TStringField
117 | FieldName = 'FIRST_NAME'
118 | Origin = 'FIRST_NAME'
119 | Size = 50
120 | end
121 | object qryMESSAGESLAST_NAME: TStringField
122 | FieldName = 'LAST_NAME'
123 | Origin = 'LAST_NAME'
124 | Size = 50
125 | end
126 | object qryMESSAGESEMAIL: TStringField
127 | FieldName = 'EMAIL'
128 | Origin = 'EMAIL'
129 | Size = 320
130 | end
131 | object qryMESSAGESDATE: TSQLTimeStampField
132 | FieldName = 'DATE'
133 | Origin = '"DATE"'
134 | Required = True
135 | end
136 | object qryMESSAGESSUBJECT: TStringField
137 | FieldName = 'SUBJECT'
138 | Origin = 'SUBJECT'
139 | Size = 998
140 | end
141 | object qryMESSAGESMESSAGE: TMemoField
142 | FieldName = 'MESSAGE'
143 | Origin = '"MESSAGE"'
144 | BlobType = ftMemo
145 | end
146 | object qryMESSAGESUNREAD: TBooleanField
147 | FieldName = 'UNREAD'
148 | Origin = 'UNREAD'
149 | Required = True
150 | end
151 | object qryMESSAGESDRAFT: TBooleanField
152 | FieldName = 'DRAFT'
153 | Origin = 'DRAFT'
154 | Required = True
155 | end
156 | object qryMESSAGESSENT: TBooleanField
157 | FieldName = 'SENT'
158 | Origin = 'SENT'
159 | Required = True
160 | end
161 | object qryMESSAGESSTARRED: TBooleanField
162 | FieldName = 'STARRED'
163 | Origin = 'STARRED'
164 | Required = True
165 | end
166 | object qryMESSAGESOUTGOING: TBooleanField
167 | FieldName = 'OUTGOING'
168 | Origin = 'OUTGOING'
169 | Required = True
170 | end
171 | end
172 | object dsrMESSAGES: TEMSDataSetResource
173 | AllowedActions = [List, Get, Post, Put, Delete]
174 | DataSet = qryMESSAGES
175 | KeyFields = 'ID'
176 | PageSize = 100
177 | Left = 660
178 | Top = 144
179 | end
180 | object qryMESSAGE_LABELS: TFDQuery
181 | MasterSource = dsMessages
182 | MasterFields = 'ID'
183 | DetailFields = 'MESSAGE_ID'
184 | Connection = FDConnection1
185 | SQL.Strings = (
186 | 'select * from MESSAGE_LABELS')
187 | Left = 916
188 | Top = 32
189 | end
190 | object dsrMESSAGE_LABELS: TEMSDataSetResource
191 | AllowedActions = [List]
192 | DataSet = qryMESSAGE_LABELS
193 | KeyFields = 'MESSAGE_ID;LABEL_ID'
194 | PageSize = 100
195 | Left = 916
196 | Top = 144
197 | end
198 | object dsMessages: TDataSource
199 | DataSet = qryMESSAGES
200 | Left = 912
201 | Top = 336
202 | end
203 | object qryLabelChildren: TFDQuery
204 | Connection = FDConnection1
205 | SQL.Strings = (
206 | 'select * from LABELS')
207 | Left = 452
208 | Top = 320
209 | end
210 | end
211 |
--------------------------------------------------------------------------------
/Delphi/ChangeViews/ModuleCode/HighScores.API.pas:
--------------------------------------------------------------------------------
1 | unit HighScores.API;
2 |
3 | // EMS Resource Module
4 |
5 | interface
6 |
7 | uses
8 | System.SysUtils, System.Classes, System.JSON,
9 | EMS.Services, EMS.ResourceAPI, EMS.ResourceTypes, FireDAC.Stan.Intf,
10 | FireDAC.Stan.Option, FireDAC.Stan.Error, FireDAC.UI.Intf, FireDAC.Phys.Intf,
11 | FireDAC.Stan.Def, FireDAC.Stan.Pool, FireDAC.Stan.Async, FireDAC.Phys,
12 | FireDAC.Phys.IB, FireDAC.Phys.IBDef, FireDAC.ConsoleUI.Wait,
13 | FireDAC.Stan.Param, FireDAC.DatS, FireDAC.DApt.Intf, FireDAC.DApt,
14 | EMS.DataSetResource, Data.DB, FireDAC.Comp.DataSet, FireDAC.Comp.Client,
15 | ChangeView.Cache, HighScores.Params;
16 |
17 | type
18 | [ResourceName('highscores')]
19 | TdataHighscoresResource = class(TDataModule)
20 | FDConnection1: TFDConnection;
21 | qryHIGHSCORES: TFDQuery;
22 |
23 | [ResourceSuffix('./')]
24 | dsrHIGHSCORES: TEMSDataSetResource;
25 | published
26 |
27 | // [EndPointRequestSummary('Tests', 'ListItems', 'Retrieves list of items', 'application/json', '')]
28 | // [EndPointResponseDetails(200, 'Ok', TAPIDoc.TPrimitiveType.spObject, TAPIDoc.TPrimitiveFormat.None, '', '')]
29 | // procedure Get(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
30 | //
31 | // [EndPointRequestSummary('Tests', 'GetItem', 'Retrieves item with specified ID', 'application/json', '')]
32 | // [EndPointRequestParameter(TAPIDocParameter.TParameterIn.Path, 'item', 'A item ID', true, TAPIDoc.TPrimitiveType.spString,
33 | // TAPIDoc.TPrimitiveFormat.None, TAPIDoc.TPrimitiveType.spString, '', '')]
34 | // [EndPointResponseDetails(200, 'Ok', TAPIDoc.TPrimitiveType.spObject, TAPIDoc.TPrimitiveFormat.None, '', '')]
35 | // [EndPointResponseDetails(404, 'Not Found', TAPIDoc.TPrimitiveType.spNull, TAPIDoc.TPrimitiveFormat.None, '', '')]
36 |
37 | [ResourceSuffix('./CHANGEVIEW/ACTIVATE')]
38 | procedure GetActivateChangeView(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
39 |
40 | [ResourceSuffix('./CHANGEVIEW/QUERY')]
41 | procedure GetQueryChangeView(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
42 |
43 | [ResourceSuffix('./CHANGEVIEW/COMMIT')]
44 | procedure GetCommitChangeView(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
45 |
46 | [ResourceSuffix('./CHANGEVIEW/ROLLBACK')]
47 | procedure GetRollBackChangeView(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
48 |
49 | end;
50 |
51 | implementation
52 |
53 | {%CLASSGROUP 'System.Classes.TPersistent'}
54 |
55 | uses Data.DBJson;
56 |
57 | {$R *.dfm}
58 |
59 | procedure TdataHighscoresResource.GetActivateChangeView(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
60 | begin
61 | // Get the ChangeView Name and the Device ID
62 | // Return the Internal Session ID where the DataModule with the active transaction is stored.
63 | var Params := TChangeViewParams.Create(AContext, ARequest, AResponse);
64 |
65 | var CVS := ChangeViewSessions.FindDeviceSession(Params.ChangeViewName, Params.DeviceID, True);
66 | CVS.Activate;
67 |
68 | if CVS <> nil then
69 | AResponse.Body.SetValue(TJSONString.Create(CVS.SubscriptionName+' Active for '+CVS.DeviceID), True)
70 | else
71 | AResponse.Body.SetValue(TJSONString.Create('Active failed'), True);
72 |
73 | end;
74 |
75 | procedure TdataHighscoresResource.GetQueryChangeView(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
76 | begin
77 | // AResponse.Body.SetValue(TJSONString.Create('Query ChangeView'), True);
78 | var Params := TChangeViewParams.Create(AContext, ARequest, AResponse);
79 |
80 | var CVS := ChangeViewSessions.FindDeviceSession(Params.ChangeViewName, Params.DeviceID, True);
81 |
82 | if CVS.FDConnection.Transaction.Active = False then
83 | CVS.Activate;
84 |
85 | var QueryOption : string := ARequest.Params.Values['query'];
86 |
87 | if LowerCase(QueryOption) = 'count' then
88 | begin
89 | CVS.qryData.Open('SELECT COUNT(*) as "COUNT" FROM HIGHSCORES')
90 | end else
91 | begin
92 | CVS.qryData.Open('SELECT * FROM HIGHSCORES');
93 | end;
94 |
95 | var lBridge := TDataSetToJSONBridge.Create;
96 | // takes the current record of the master query and converts it to a JSON object
97 | lBridge.Dataset := CVS.qryData;
98 | lBridge.IncludeNulls := True;
99 | // specifies that the we only require to process the current record
100 | lBridge.Area := TJSONDataSetArea.All;
101 | // adds the master record as an object in the JSON result
102 | lBridge.Produce(AResponse.Body.JSONWriter);
103 |
104 | end;
105 |
106 | procedure TdataHighscoresResource.GetCommitChangeView(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
107 | begin
108 | var Params := TChangeViewParams.Create(AContext, ARequest, AResponse);
109 | var CVC := ChangeViewSessions.FindDeviceSession(Params.ChangeViewName, Params.DeviceID, True);
110 | CVC.CommitChangeView;
111 |
112 | // Remove from Cache... all done!!
113 | var CVS := ChangeViewSessions.FindChangeViewSessions(Params.ChangeViewName);
114 | if Assigned(CVS) then
115 | CVS.CloseSession(Params.DeviceID);
116 | AResponse.Body.SetValue(TJSONString.Create(Format('ChangeView %s for %s Commited', [Params.ChangeViewName, Params.DeviceID])), True);
117 | end;
118 |
119 | procedure TdataHighscoresResource.GetRollBackChangeView(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
120 | begin
121 | var Params := TChangeViewParams.Create(AContext, ARequest, AResponse);
122 | var CVC := ChangeViewSessions.FindDeviceSession(Params.ChangeViewName, Params.DeviceID, True);
123 | CVC.RollBackChangeView;
124 |
125 | // Remove from Cache... all done!!
126 | var CVS := ChangeViewSessions.FindChangeViewSessions(Params.ChangeViewName);
127 | if Assigned(CVS) then
128 | CVS.CloseSession(Params.DeviceID);
129 | AResponse.Body.SetValue(TJSONString.Create(Format('ChangeView %s for %s Rolledback', [Params.ChangeViewName, Params.DeviceID])), True);
130 |
131 | end;
132 |
133 |
134 | procedure Register;
135 | begin
136 | RegisterResource(TypeInfo(TdataHighscoresResource));
137 | end;
138 |
139 | initialization
140 | Register;
141 | end.
142 |
143 |
144 |
--------------------------------------------------------------------------------
/SenchaMail/unitData.pas:
--------------------------------------------------------------------------------
1 | unit unitData;
2 |
3 | // EMS Resource Module
4 |
5 | interface
6 |
7 | uses
8 | System.SysUtils, System.Classes, System.JSON,
9 | EMS.Services, EMS.ResourceAPI, EMS.ResourceTypes, FireDAC.Stan.Intf,
10 | FireDAC.Stan.Option, FireDAC.Stan.Error, FireDAC.UI.Intf, FireDAC.Phys.Intf,
11 | FireDAC.Stan.Def, FireDAC.Stan.Pool, FireDAC.Stan.Async, FireDAC.Phys,
12 | FireDAC.Phys.IB, FireDAC.Phys.IBDef, FireDAC.ConsoleUI.Wait,
13 | FireDAC.Stan.Param, FireDAC.DatS, FireDAC.DApt.Intf, FireDAC.DApt,
14 | EMS.DataSetResource, Data.DB, FireDAC.Comp.DataSet, FireDAC.Comp.Client;
15 |
16 | type
17 | [ResourceName('data')]
18 | TMailResource1 = class(TDataModule)
19 | FDConnection1: TFDConnection;
20 | qryCONTACTS: TFDQuery;
21 | [ResourceSuffix('contacts')]
22 | dsrCONTACTS: TEMSDataSetResource;
23 | qryLABELS: TFDQuery;
24 | [ResourceSuffix('labels')]
25 | dsrLABELS: TEMSDataSetResource;
26 | qryMESSAGES: TFDQuery;
27 | [ResourceSuffix('messages')]
28 | dsrMESSAGES: TEMSDataSetResource;
29 | qryMESSAGE_LABELS: TFDQuery;
30 | [ResourceSuffix('message_labels')]
31 | dsrMESSAGE_LABELS: TEMSDataSetResource;
32 | dsMessages: TDataSource;
33 | qryLabelChildren: TFDQuery;
34 | qryLABELSID: TIntegerField;
35 | qryLABELSPARENT_ID: TIntegerField;
36 | qryLABELSNAME: TStringField;
37 | qryLABELSLEAF: TBooleanField;
38 | qryLABELSEXPANDED: TBooleanField;
39 | qryCONTACTSID: TFDAutoIncField;
40 | qryCONTACTSFIRST_NAME: TStringField;
41 | qryCONTACTSLAST_NAME: TStringField;
42 | qryCONTACTSEMAIL: TStringField;
43 | qryMESSAGESFIRST_NAME: TStringField;
44 | qryMESSAGESLAST_NAME: TStringField;
45 | qryMESSAGESEMAIL: TStringField;
46 | qryMESSAGESDATE: TSQLTimeStampField;
47 | qryMESSAGESSUBJECT: TStringField;
48 | qryMESSAGESMESSAGE: TMemoField;
49 | qryMESSAGESUNREAD: TBooleanField;
50 | qryMESSAGESDRAFT: TBooleanField;
51 | qryMESSAGESSENT: TBooleanField;
52 | qryMESSAGESSTARRED: TBooleanField;
53 | qryMESSAGESOUTGOING: TBooleanField;
54 | qryMESSAGESID: TIntegerField;
55 |
56 | published
57 | [ResourceSuffix('messagesfull')]
58 | [EndPointRequestSummary('messages', 'Get messages (with labels)', 'Retrieves list of messages with their labels', 'application/json', '')]
59 | [EndPointResponseDetails(200, 'Ok', TAPIDoc.TPrimitiveType.spObject, TAPIDoc.TPrimitiveFormat.None, '', '')]
60 | procedure Get(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
61 |
62 | [ResourceSuffix('labelsnested')]
63 | [EndPointRequestSummary('labels', 'Get list of labels in their nested structure', 'Retrieves list of labels', 'application/json', '')]
64 | [EndPointResponseDetails(200, 'Ok', TAPIDoc.TPrimitiveType.spObject, TAPIDoc.TPrimitiveFormat.None, '', '')]
65 | procedure GetLabels(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
66 | end;
67 |
68 | implementation
69 |
70 | {%CLASSGROUP 'System.Classes.TPersistent'}
71 |
72 | {$R *.dfm}
73 |
74 | procedure ConvertRecordToJSONObject(
75 | const AResponse: TEndpointResponse;
76 | DataSet : TDataSet;
77 | MasterField : string = '';
78 | IncFieldName : Boolean = True);
79 | var
80 | FieldIdx : Integer;
81 | begin
82 | for FieldIdx := 0 to DataSet.FieldCount -1 do
83 | begin
84 | // Skip master field
85 | if (MasterField > '') and
86 | (Uppercase(MasterField) =
87 | Uppercase(DataSet.Fields[FieldIdx].
88 | FieldName)) then
89 | Continue;
90 |
91 | // Add name value pairs (except if labels array, just write the values)
92 | if IncFieldName then
93 | if DataSet.Fields[FieldIdx].DisplayName > '' then
94 | AResponse.Body.JSONWriter.WritePropertyName(DataSet.Fields[FieldIdx].DisplayName)
95 | else
96 | AResponse.Body.JSONWriter.WritePropertyName(DataSet.Fields[FieldIdx].FieldName);
97 |
98 | case DataSet.Fields[FieldIdx].DataType of
99 | ftSmallint,
100 | ftInteger,
101 | ftWord,
102 | ftLargeint,
103 | ftLongWord,
104 | ftShortint : AResponse.Body.JSONWriter.WriteValue(DataSet.Fields[FieldIdx].AsInteger);
105 |
106 | ftFloat,
107 | ftCurrency,
108 | ftExtended,
109 | ftSingle : AResponse.Body.JSONWriter.WriteValue(DataSet.Fields[FieldIdx].AsFloat);
110 |
111 | ftBoolean : AResponse.Body.JSONWriter.WriteValue(DataSet.Fields[FieldIdx].AsBoolean);
112 |
113 | ftDate,
114 | ftDateTime,
115 | ftTimeStamp,
116 | ftOraTimeStamp : AResponse.Body.JSONWriter.WriteValue(DataSet.Fields[FieldIdx].AsDateTime);
117 |
118 | else
119 | AResponse.Body.JSONWriter.WriteValue(DataSet.Fields[FieldIdx].AsString);
120 | end;
121 | end;
122 | end;
123 |
124 | procedure TMailResource1.Get(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
125 | begin
126 | qryMESSAGES.Open;
127 | qryMESSAGE_LABELS.Open('SELECT * FROM MESSAGE_LABELS WHERE MESSAGE_ID = :ID');
128 |
129 | AResponse.Body.JSONWriter.WriteStartArray;
130 |
131 | qryMessages.First;
132 | while not qryMessages.Eof do begin
133 | // Build Message
134 | AResponse.Body.JSONWriter.WriteStartObject;
135 | ConvertRecordToJSONObject(AResponse,qryMessages);
136 |
137 | // Add the Labels
138 | AResponse.Body.JSONWriter.WritePropertyName('labels');
139 | AResponse.Body.JSONWriter.WriteStartArray;
140 | qryMessage_Labels.First;
141 |
142 | while not qryMessage_Labels.Eof do begin
143 | ConvertRecordToJSONObject(AResponse, qryMessage_Labels,'MESSAGE_ID',False);
144 | qryMessage_Labels.Next;
145 | end;
146 |
147 | AResponse.Body.JSONWriter.WriteEndArray;
148 | AResponse.Body.JSONWriter.WriteEndObject;
149 | qryMessages.Next;
150 | end;
151 | AResponse.Body.JSONWriter.WriteEndArray;
152 |
153 | end;
154 |
155 | procedure TMailResource1.GetLabels(const AContext: TEndpointContext;
156 | const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
157 |
158 | procedure loadChlildren(ParentQry:TFDDataSet);
159 | var
160 | Qry : TFDMemTable;
161 | begin
162 | AResponse.Body.JSONWriter.WritePropertyName('children');
163 | AResponse.Body.JSONWriter.WriteStartArray;
164 |
165 | if qryLabelChildren.Locate('PARENT_ID', ParentQry.FieldByName('ID').AsInteger) then begin
166 |
167 | Qry := TFDMemTable.Create(Self);
168 | try
169 | Qry.CloneCursor(qryLabelChildren,True);
170 | Qry.Filter := 'PARENT_ID = '+ParentQry.FieldByName('ID').AsString;
171 | Qry.Filtered := True;
172 |
173 |
174 | while not Qry.Eof do begin
175 | AResponse.Body.JSONWriter.WriteStartObject;
176 | ConvertRecordToJSONObject(AResponse, Qry,'PARENT_ID');
177 | loadChlildren(Qry);
178 | AResponse.Body.JSONWriter.WriteEndObject;
179 | Qry.Next;
180 | end;
181 |
182 | finally
183 | Qry.Free;
184 | end;
185 | end;
186 |
187 | AResponse.Body.JSONWriter.WriteEndArray;
188 | end;
189 |
190 | begin
191 | // Get the top level list
192 | qryLABELS.Open('SELECT * FROM LABELS WHERE PARENT_ID IS NULL ORDER BY ID');
193 | // List of all linked nodes to work with
194 | qryLabelChildren.Open('SELECT * FROM LABELS WHERE PARENT_ID IS NOT NULL ORDER BY PARENT_ID, ID');
195 |
196 | AResponse.Body.JSONWriter.WriteStartArray;
197 |
198 | qryLABELS.First;
199 | while not qryLABELS.Eof do begin
200 | // Build Message
201 | AResponse.Body.JSONWriter.WriteStartObject;
202 | ConvertRecordToJSONObject(AResponse,qryLabels,'PARENT_ID');
203 | // Add child labels Labels
204 | loadChlildren(qryLABELS);
205 |
206 | AResponse.Body.JSONWriter.WriteEndObject;
207 | qryLABELS.Next;
208 | end;
209 | AResponse.Body.JSONWriter.WriteEndArray;
210 | end;
211 |
212 | procedure Register;
213 | begin
214 | RegisterResource(TypeInfo(TMailResource1));
215 | end;
216 |
217 |
218 | initialization
219 | Register;
220 | end.
221 |
222 |
223 |
--------------------------------------------------------------------------------
/Delphi/TasksExample/Simple Client/FormSimple.fmx:
--------------------------------------------------------------------------------
1 | object Form1: TForm1
2 | Left = 0
3 | Top = 0
4 | Caption = 'Form1'
5 | ClientHeight = 480
6 | ClientWidth = 764
7 | FormFactor.Width = 320
8 | FormFactor.Height = 480
9 | FormFactor.Devices = [Desktop]
10 | DesignerMasterStyle = 0
11 | object BindNavigator1: TBindNavigator
12 | Align = Bottom
13 | Position.Y = 455.000000000000000000
14 | Size.Width = 764.000000000000000000
15 | Size.Height = 25.000000000000000000
16 | Size.PlatformDefault = False
17 | TabOrder = 7
18 | DataSource = BindSourceDB2
19 | xRadius = 4.000000000000000000
20 | yRadius = 4.000000000000000000
21 | end
22 | object Layout1: TLayout
23 | Align = Top
24 | Size.Width = 764.000000000000000000
25 | Size.Height = 50.000000000000000000
26 | Size.PlatformDefault = False
27 | TabOrder = 8
28 | object Button1: TButton
29 | Position.X = 8.000000000000000000
30 | Position.Y = 8.000000000000000000
31 | TabOrder = 1
32 | Text = 'Fetch'
33 | OnClick = Button1Click
34 | end
35 | object Button2: TButton
36 | Position.X = 96.000000000000000000
37 | Position.Y = 8.000000000000000000
38 | TabOrder = 0
39 | Text = 'Save'
40 | OnClick = Button2Click
41 | end
42 | object Button3: TButton
43 | Position.X = 192.000000000000000000
44 | Position.Y = 8.000000000000000000
45 | Size.Width = 121.000000000000000000
46 | Size.Height = 22.000000000000000000
47 | Size.PlatformDefault = False
48 | TabOrder = 2
49 | Text = 'Change Count'
50 | OnClick = Button3Click
51 | end
52 | end
53 | object TabControl1: TTabControl
54 | Align = Client
55 | Size.Width = 764.000000000000000000
56 | Size.Height = 405.000000000000000000
57 | Size.PlatformDefault = False
58 | TabIndex = 1
59 | TabOrder = 19
60 | TabPosition = PlatformDefault
61 | Sizes = (
62 | 764s
63 | 379s
64 | 764s
65 | 379s)
66 | object TabItem1: TTabItem
67 | CustomIcon = <
68 | item
69 | end>
70 | IsSelected = False
71 | Size.Width = 69.000000000000000000
72 | Size.Height = 26.000000000000000000
73 | Size.PlatformDefault = False
74 | StyleLookup = ''
75 | TabOrder = 0
76 | Text = 'TabItem1'
77 | ExplicitSize.cx = 69.000000000000000000
78 | ExplicitSize.cy = 26.000000000000000000
79 | object StringGrid1: TStringGrid
80 | Align = Client
81 | CanFocus = True
82 | ClipChildren = True
83 | Size.Width = 764.000000000000000000
84 | Size.Height = 379.000000000000000000
85 | Size.PlatformDefault = False
86 | TabOrder = 0
87 | RowCount = 0
88 | Viewport.Width = 760.000000000000000000
89 | Viewport.Height = 354.000000000000000000
90 | end
91 | end
92 | object TabItem2: TTabItem
93 | CustomIcon = <
94 | item
95 | end>
96 | IsSelected = True
97 | Size.Width = 69.000000000000000000
98 | Size.Height = 26.000000000000000000
99 | Size.PlatformDefault = False
100 | StyleLookup = ''
101 | TabOrder = 0
102 | Text = 'TabItem2'
103 | ExplicitSize.cx = 69.000000000000000000
104 | ExplicitSize.cy = 26.000000000000000000
105 | object Memo1: TMemo
106 | Touch.InteractiveGestures = [Pan, LongTap, DoubleTap]
107 | DataDetectorTypes = []
108 | Align = Top
109 | Position.Y = 17.000000000000000000
110 | Size.Width = 764.000000000000000000
111 | Size.Height = 72.000000000000000000
112 | Size.PlatformDefault = False
113 | TabOrder = 1
114 | Viewport.Width = 760.000000000000000000
115 | Viewport.Height = 68.000000000000000000
116 | end
117 | object Label1: TLabel
118 | Align = Top
119 | Size.Width = 764.000000000000000000
120 | Size.Height = 17.000000000000000000
121 | Size.PlatformDefault = False
122 | Text = 'Post Response'
123 | TabOrder = 3
124 | end
125 | object Label2: TLabel
126 | Align = Top
127 | Position.Y = 89.000000000000000000
128 | Size.Width = 764.000000000000000000
129 | Size.Height = 17.000000000000000000
130 | Size.PlatformDefault = False
131 | Text = 'Post Update Body'
132 | TabOrder = 2
133 | end
134 | object MemoPostBody: TMemo
135 | Touch.InteractiveGestures = [Pan, LongTap, DoubleTap]
136 | DataDetectorTypes = []
137 | Align = Top
138 | Position.Y = 106.000000000000000000
139 | Size.Width = 764.000000000000000000
140 | Size.Height = 72.000000000000000000
141 | Size.PlatformDefault = False
142 | TabOrder = 0
143 | Viewport.Width = 760.000000000000000000
144 | Viewport.Height = 68.000000000000000000
145 | end
146 | end
147 | end
148 | object BindingsList1: TBindingsList
149 | Methods = <>
150 | OutputConverters = <>
151 | Left = 28
152 | Top = 357
153 | object LinkGridToDataSourceBindSourceDB2: TLinkGridToDataSource
154 | Category = 'Quick Bindings'
155 | DataSource = BindSourceDB2
156 | GridControl = StringGrid1
157 | Columns = <>
158 | end
159 | end
160 | object RESTClient1: TRESTClient
161 | Accept = 'application/json, text/plain; q=0.9, text/html;q=0.8,'
162 | AcceptCharset = 'utf-8, *;q=0.8'
163 | BaseURL = 'http://localhost:8080'
164 | Params = <>
165 | Left = 136
166 | Top = 88
167 | end
168 | object RESTRequestGet: TRESTRequest
169 | AssignedValues = [rvConnectTimeout, rvReadTimeout]
170 | Client = RESTClient1
171 | Params = <>
172 | Resource = 'data/tasks/'
173 | Response = RESTResponseGet
174 | Left = 136
175 | Top = 136
176 | end
177 | object RESTResponseGet: TRESTResponse
178 | ContentType = 'application/json'
179 | Left = 136
180 | Top = 192
181 | end
182 | object RESTResponseDataSetAdapterGet: TRESTResponseDataSetAdapter
183 | Active = True
184 | Dataset = FDMemTable1
185 | FieldDefs = <>
186 | Response = RESTResponseGet
187 | StringFieldSize = 50
188 | Left = 136
189 | Top = 248
190 | end
191 | object FDMemTable1: TFDMemTable
192 | Active = True
193 | FieldDefs = <
194 | item
195 | Name = 'ID'
196 | DataType = ftWideString
197 | Size = 50
198 | end
199 | item
200 | Name = 'FIRST_NAME'
201 | DataType = ftWideString
202 | Size = 50
203 | end
204 | item
205 | Name = 'LAST_NAME'
206 | DataType = ftWideString
207 | Size = 50
208 | end
209 | item
210 | Name = 'EMAIL'
211 | DataType = ftWideString
212 | Size = 50
213 | end
214 | item
215 | Name = 'DATE'
216 | DataType = ftWideString
217 | Size = 50
218 | end
219 | item
220 | Name = 'SUBJECT'
221 | DataType = ftWideString
222 | Size = 50
223 | end
224 | item
225 | Name = 'UNREAD'
226 | DataType = ftWideString
227 | Size = 50
228 | end
229 | item
230 | Name = 'DRAFT'
231 | DataType = ftWideString
232 | Size = 50
233 | end
234 | item
235 | Name = 'SENT'
236 | DataType = ftWideString
237 | Size = 50
238 | end
239 | item
240 | Name = 'STARRED'
241 | DataType = ftWideString
242 | Size = 50
243 | end
244 | item
245 | Name = 'OUTGOING'
246 | DataType = ftWideString
247 | Size = 50
248 | end
249 | item
250 | Name = 'MESSAGE'
251 | DataType = ftWideString
252 | Size = 50
253 | end>
254 | IndexDefs = <>
255 | FetchOptions.AssignedValues = [evMode]
256 | FetchOptions.Mode = fmAll
257 | ResourceOptions.AssignedValues = [rvSilentMode]
258 | ResourceOptions.SilentMode = True
259 | UpdateOptions.AssignedValues = [uvUpdateChngFields, uvUpdateMode, uvLockMode, uvLockPoint, uvLockWait, uvRefreshMode, uvFetchGeneratorsPoint, uvCheckRequired, uvCheckReadOnly, uvCheckUpdatable]
260 | UpdateOptions.LockWait = True
261 | UpdateOptions.FetchGeneratorsPoint = gpNone
262 | UpdateOptions.CheckRequired = False
263 | StoreDefs = True
264 | Left = 272
265 | Top = 312
266 | end
267 | object BindSourceDB2: TBindSourceDB
268 | DataSet = FDMemTable1
269 | ScopeMappings = <>
270 | Left = 272
271 | Top = 368
272 | end
273 | end
274 |
--------------------------------------------------------------------------------
/Delphi/REST.DataUpdater.pas:
--------------------------------------------------------------------------------
1 | unit REST.DataUpdater;
2 |
3 | interface
4 |
5 | uses System.Classes, REST.Client, REST.Response.Adapter,
6 | Data.DB, FireDAC.Comp.DataSet, FireDAC.Comp.Client, REST.Types;
7 |
8 | type
9 | TRestDataSetUpdater = class(TComponent)
10 | type
11 | TRDSUTransport = class(TComponent)
12 | private
13 | FDataSet : TFDDataSet;
14 | FRequest : TRESTRequest;
15 | FResponse : TRESTResponse;
16 | FDataSetAdapter: TRESTRequestDataSetAdapter;
17 | function RDSU : TRestDataSetUpdater;
18 | public
19 | // Need to create constructor, set these options then put into the thread model.
20 | constructor Create(AOwner : TRestDataSetUpdater; UpdateKind : TRESTRequestMethod); reintroduce;
21 | function Execute(AutoUpdateDataSetSavePoint : Boolean = True) : Boolean;
22 | end;
23 |
24 | private
25 | FRESTClient : TRESTClient;
26 | FDataSet : TFDDataSet;
27 | FKeyFieldName: string;
28 | FslError : TStringList;
29 | FResourcePut: string;
30 | FResourceDelete: string;
31 | FResourcePost: string;
32 |
33 | procedure SetDataSet(const Value: TFDDataSet);
34 | procedure SetClient(const Value: TRESTClient);
35 | procedure SetKeyFieldName(const Value: string);
36 | procedure LogError(aErrorMessage: string);
37 | procedure SetResourceDelete(const Value: string);
38 | procedure SetResourcePost(const Value: string);
39 | procedure SetResourcePut(const Value: string);
40 | public
41 | constructor Create(AOwner : TComponent); reintroduce; overload;
42 | constructor Create(AOwner : TComponent; ARESTClient : TRESTClient; AResource, AKeyFieldName : string; ADataSet : TFDDataSet); reintroduce; overload;
43 | destructor Destroy; override;
44 |
45 | function ApplyRemoteUpdates(AutoUpdateDataSetSavePoint : Boolean = True) : Boolean;
46 |
47 | property DataSet : TFDDataSet read FDataSet write SetDataSet;
48 |
49 | // Insert
50 | property ResourcePost : string read FResourcePost write SetResourcePost;
51 | // Update
52 | property ResourcePut : string read FResourcePut write SetResourcePut;
53 | // Delete
54 | property ResourceDelete : string read FResourceDelete write SetResourceDelete;
55 |
56 | property Client : TRESTClient read FRESTClient write SetClient;
57 |
58 | // Name the paramater for the ID to be the same as the field in the dataset, this way it will get set.
59 | property KeyFieldName : string read FKeyFieldName write SetKeyFieldName;
60 |
61 | property ErrorLog : TStringList read FslError;
62 | end;
63 |
64 | implementation
65 |
66 | uses Data.DBJson, System.SysUtils;
67 |
68 | { TRestDataSetUpdater }
69 |
70 | function TRestDataSetUpdater.ApplyRemoteUpdates(AutoUpdateDataSetSavePoint : Boolean = True): Boolean;
71 | var
72 | ResultI, ResultU, ResultD : Boolean;
73 | begin
74 | // Check Client is set.
75 | Assert(Assigned(DataSet),'DataSet Missing');
76 | Assert(Assigned(Client),'RESTClient Connection missing');
77 | Assert(KeyFieldName > '','Key FieldName Missing');
78 |
79 | if not DataSet.UpdatesPending then
80 | Exit(True);
81 |
82 | FslError.Clear;
83 |
84 | //
85 | ResultI := False;
86 | ResultU := False;
87 | ResultD := False;
88 |
89 | var InsertTransport := TRDSUTransport.Create(Self,TRESTRequestMethod.rmPOST);
90 | try
91 | try
92 | ResultI := InsertTransport.Execute(AutoUpdateDataSetSavePoint);
93 | except
94 | on e:Exception do
95 | LogError('rmPOST Error: '+e.Message);
96 | end;
97 | finally
98 | InsertTransport.Free;
99 | end;
100 |
101 | // Updates
102 | var UpdateTransport := TRDSUTransport.Create(Self,TRESTRequestMethod.rmPUT);
103 | try
104 | try
105 | ResultU := UpdateTransport.Execute(AutoUpdateDataSetSavePoint);
106 | except
107 | on e:Exception do
108 | LogError('rmPUT Error: '+e.Message);
109 | end;
110 | finally
111 | UpdateTransport.Free;
112 | end;
113 |
114 | // Delete
115 | var DeleteTransport := TRDSUTransport.Create(Self,TRESTRequestMethod.rmDELETE);
116 | try
117 | try
118 | ResultD := DeleteTransport.Execute(AutoUpdateDataSetSavePoint);
119 | except
120 | on e:Exception do
121 | LogError('rmDELETE Error: '+e.Message);
122 | end;
123 | finally
124 | DeleteTransport.Free;
125 | end;
126 |
127 | Result := ResultI and ResultU and ResultD;
128 |
129 | if AutoUpdateDataSetSavePoint and Result then
130 | FDataSet.CommitUpdates; // Clear the cache.
131 | end;
132 |
133 | constructor TRestDataSetUpdater.Create(AOwner: TComponent);
134 | begin
135 | inherited Create(AOwner);
136 | FslError := TStringList.Create;
137 | FRESTClient := nil;
138 | end;
139 |
140 | constructor TRestDataSetUpdater.Create(AOwner: TComponent;
141 | ARESTClient: TRESTClient; AResource, AKeyFieldName: string; ADataSet : TFDDataSet);
142 | begin
143 | Create(AOwner);
144 | Client := ARESTClient;
145 |
146 | if not AResource.EndsWith('/') then
147 | AResource := AResource+'/';
148 |
149 | // Insert (Put} doesn't take a param...
150 | ResourcePost := AResource;
151 | // Update and delete, use the Param. These can be overriden after creation.
152 | ResourcePut := AResource+'{'+AKeyFieldName+'}';
153 | ResourceDelete := AResource+'{'+AKeyFieldName+'}';
154 |
155 | DataSet := ADataSet;
156 | KeyFieldName := AKeyFieldName;
157 | end;
158 |
159 | destructor TRestDataSetUpdater.Destroy;
160 | begin
161 | FslError.Free;
162 | inherited;
163 | end;
164 |
165 | procedure TRestDataSetUpdater.LogError(aErrorMessage: string);
166 | begin
167 | FslError.Add(aErrorMessage);
168 | end;
169 |
170 | procedure TRestDataSetUpdater.SetClient(const Value: TRESTClient);
171 | begin
172 | FRESTClient := Value;
173 | end;
174 |
175 | procedure TRestDataSetUpdater.SetDataSet(const Value: TFDDataSet);
176 | begin
177 | FDataset := Value;
178 | end;
179 |
180 | procedure TRestDataSetUpdater.SetKeyFieldName(const Value: string);
181 | begin
182 | FKeyFieldName := Value;
183 | end;
184 |
185 | procedure TRestDataSetUpdater.SetResourceDelete(const Value: string);
186 | begin
187 | FResourceDelete := Value;
188 | end;
189 |
190 | procedure TRestDataSetUpdater.SetResourcePost(const Value: string);
191 | begin
192 | FResourcePost := Value;
193 | end;
194 |
195 | procedure TRestDataSetUpdater.SetResourcePut(const Value: string);
196 | begin
197 | FResourcePut := Value;
198 | end;
199 |
200 | { TRestDataSetUpdater.TRDSUTransport }
201 |
202 | constructor TRestDataSetUpdater.TRDSUTransport.Create(AOwner : TRestDataSetUpdater; UpdateKind : TRESTRequestMethod);
203 | begin
204 | Assert(AOwner <> nil,'Owner not Assigned');
205 |
206 | inherited Create(AOwner);
207 |
208 | FDataSet := TFDMemTable.Create(Self);
209 | FDataSet.Data := AOwner.DataSet.Delta;
210 |
211 | FRequest := TRESTRequest.Create(Self);
212 | FRequest.Client := AOwner.Client;
213 |
214 | FResponse := TRESTResponse.Create(Self);
215 | FRequest.Response := FResponse;
216 |
217 | case UpdateKind of
218 | rmPOST : FRequest.Resource := AOwner.ResourcePost;
219 | rmPUT : FRequest.Resource := AOwner.ResourcePut;
220 | rmDELETE : FRequest.Resource := AOwner.ResourceDelete;
221 | //rmGET : ;
222 | //rmPATCH: ;
223 | else
224 | FRequest.Resource := AOwner.ResourcePut;
225 | end;
226 |
227 | FRequest.Method := UpdateKind;
228 |
229 | FDataSetAdapter := TRESTRequestDataSetAdapter.Create(Self);
230 | FDataSetAdapter.Area := TJSONDataSetArea.Current;
231 | FDataSetAdapter.Request := FRequest;
232 | FDataSetAdapter.Dataset := FDataSet;
233 |
234 | // Ignore Nulls on Insert.
235 | if UpdateKind = rmPost then
236 | FDataSetAdapter.IncludeNulls := False;
237 |
238 | FDataSetAdapter.AutoUpdate := True;
239 | end;
240 |
241 | function TRestDataSetUpdater.TRDSUTransport.Execute(AutoUpdateDataSetSavePoint : Boolean = True) : Boolean;
242 | begin
243 |
244 | case FRequest.Method of
245 | // Insert
246 | rmPOST : FDataSet.FilterChanges := [rtInserted];
247 | // Update
248 | rmPUT,
249 | rmPATCH : FDataSet.FilterChanges := [rtModified];
250 | // Delete
251 | rmDELETE : FDataSet.FilterChanges := [rtDeleted];
252 | else
253 | //Should never be used - e.g. rmGET - Force a failure if it is.
254 | Exit(False);
255 | end;
256 |
257 | // If nothing to update, all is good, return true;
258 | if FDataSet.RecordCount = 0 then
259 | Exit(True);
260 |
261 | // Currently, it has to be done record by record.
262 | // Future update, check each field to build the data to push back when its a Patch.
263 | try
264 | Result := True;
265 |
266 | var KeyStr := RDSU.KeyFieldName;
267 | var FParam := FRequest.Params.ParameterByName(KeyStr);
268 |
269 | while not FDataSet.Eof do begin
270 | // AutoUpdate will update the REST Request body data
271 | // Update URL Param for current ITEM
272 | if Assigned(FParam) then
273 | FParam.Value := FDataSet.FieldByName(KeyStr).AsString;
274 |
275 | try
276 | FRequest.Execute;
277 | finally
278 | Result := (FResponse.StatusCode >= 200) and (FResponse.StatusCode <= 205);
279 | end;
280 |
281 | FDataSet.Next;
282 | end;
283 |
284 |
285 | // This isn't applying to the master dataset.... Is there away to do this record by record?
286 | if AutoUpdateDataSetSavePoint and Result then
287 | FDataSet.CommitUpdates; // Clear the cache.
288 |
289 |
290 | except
291 | on E:Exception do begin
292 | // Log the error
293 | RDSU.LogError('Execute error: '+e.Message);
294 | RDSU.LogError('DataPacket: '+FRequest.GetFullRequestBody);
295 | Result := False;
296 | end;
297 | end;
298 |
299 | end;
300 |
301 | function TRestDataSetUpdater.TRDSUTransport.RDSU: TRestDataSetUpdater;
302 | begin
303 | Result := TRestDataSetUpdater(Owner);
304 | end;
305 |
306 | end.
307 |
--------------------------------------------------------------------------------
/Delphi/ChangeViews/ModuleCode/ChangeView.Cache.pas:
--------------------------------------------------------------------------------
1 | unit ChangeView.Cache;
2 |
3 | interface
4 |
5 | uses
6 | System.SysUtils, System.Classes, System.Generics.Collections,
7 | ChangeView.DataConnection, System.SyncObjs, System.Threading;
8 |
9 | type
10 |
11 | // A list of Sessions for a ChangeView based on the DeviceID as the key
12 | TChangeViewSessions = class(TComponent)
13 | type
14 | TChangeViewSessionItems = TDictionary;
15 | strict private
16 | FChangeViewName: string;
17 | FCriticalSection : TCriticalSection;
18 | FSessions : TChangeViewSessionItems;
19 | procedure EnterCriticalSection;
20 | procedure LeaveCriticalSection;
21 | function GetCount: Integer;
22 | public
23 | constructor Create(AOwner : TComponent; AChangeViewName : String); reintroduce;
24 | destructor Destroy; override;
25 |
26 | function FindSession(ADeviceID : string):TChangeViewConnection;
27 | function NewSession(ADeviceID : string):TChangeViewConnection;
28 | procedure CloseSession(ADeviceID : string);
29 | procedure CloseInactiveSession(InactiveTimeInSeconds : Integer);
30 | procedure GetStats(AOutput: TStrings);
31 |
32 | property Count : Integer read GetCount;
33 | property ChangeViewName : string read FChangeViewName;
34 | end;
35 |
36 |
37 | // ChangeView Name and a List of Sessions for that ChangeView
38 | TChangeViewSessionList = TDictionary;
39 |
40 | TChangeViewSessionManager = class(TComponent)
41 | strict private
42 | FChangeViewSessionList : TChangeViewSessionList;
43 | FCriticalSectionManager : TCriticalSection;
44 |
45 | procedure EnterCriticalSection;
46 | procedure LeaveCriticalSection;
47 | public
48 | constructor Create(AOwner : TComponent); Reintroduce;
49 | destructor Destroy; override;
50 |
51 | function FindDeviceSession(const ChangeViewName : string; const DeviceID : string; AutoCreate : Boolean = False): TChangeViewConnection;
52 | function FindChangeViewSessions(const ChangeViewName : string; AutoCreate : Boolean = False): TChangeViewSessions;
53 |
54 | procedure Sweep(SecondsInactive : Integer);
55 |
56 | procedure GetStats(AOutput: TStrings; const QuickStats : Boolean = False);
57 | end;
58 |
59 | var
60 | FChangeViewSessionManager : TChangeViewSessionManager;
61 |
62 | function ChangeViewSessions : TChangeViewSessionManager;
63 |
64 |
65 | implementation
66 |
67 | uses System.DateUtils;
68 |
69 |
70 | function ChangeViewSessions : TChangeViewSessionManager;
71 | begin
72 | Result := FChangeViewSessionManager;
73 | end;
74 |
75 |
76 | constructor TChangeViewSessionManager.Create(AOwner: TComponent);
77 | begin
78 | inherited Create(AOwner);
79 | FCriticalSectionManager := TCriticalSection.Create;
80 | FChangeViewSessionList := TChangeViewSessionList.Create;
81 | end;
82 |
83 | destructor TChangeViewSessionManager.Destroy;
84 | begin
85 | FChangeViewSessionList.Free;
86 | FCriticalSectionManager.Free;
87 | inherited Destroy;
88 | end;
89 |
90 | procedure TChangeViewSessionManager.EnterCriticalSection;
91 | begin
92 | FCriticalSectionManager.Enter;
93 | end;
94 |
95 | function TChangeViewSessionManager.FindChangeViewSessions(
96 | const ChangeViewName: string; AutoCreate : Boolean = False): TChangeViewSessions;
97 | var
98 | FChangeViewSessions : TChangeViewSessions;
99 | begin
100 | FChangeViewSessionList.TryGetValue(ChangeViewName, FChangeViewSessions);
101 |
102 | if (FChangeViewSessions = nil) and AutoCreate then
103 | begin
104 | FCriticalSectionManager.Enter;
105 | try
106 | FChangeViewSessions := TChangeViewSessions.Create(Self, ChangeViewName);
107 | if not FChangeViewSessionList.TryAdd(ChangeViewName,FChangeViewSessions) then
108 | begin
109 | FChangeViewSessions.Free;
110 | Exit(nil);
111 | end;
112 | finally
113 | FCriticalSectionManager.Leave;
114 | end;
115 | end;
116 |
117 | Result := FChangeViewSessions;
118 |
119 | end;
120 |
121 | function TChangeViewSessionManager.FindDeviceSession(const ChangeViewName : string; const DeviceID : string; AutoCreate : Boolean = False): TChangeViewConnection;
122 | var
123 | FChangeViewSessions : TChangeViewSessions;
124 |
125 | begin
126 | FChangeViewSessions := FindChangeViewSessions(ChangeViewName, AutoCreate);
127 |
128 | if FChangeViewSessions <> nil then begin
129 |
130 | var FCurrSession := FChangeViewSessions.FindSession(DeviceID);
131 |
132 | if (FCurrSession = nil) and AutoCreate then
133 | begin
134 | FCurrSession := FChangeViewSessions.NewSession(DeviceID);
135 | end;
136 |
137 | Result := FCurrSession;
138 | Result.MarkAsActive;
139 |
140 | end else
141 | Result := nil;
142 |
143 | end;
144 |
145 | procedure TChangeViewSessionManager.GetStats(AOutput: TStrings; const QuickStats : Boolean);
146 |
147 | procedure Log(s : string);
148 | begin
149 | AOutput.Add(s);
150 | end;
151 |
152 | begin
153 | AOutput.BeginUpdate;
154 | try
155 | AOutput.Clear;
156 |
157 | Log( Format('Total ChangeViews : %d',[FChangeViewSessionList.Count] ));
158 | Log( '' );
159 | for var CVS in FChangeViewSessionList do begin
160 |
161 | if QuickStats then
162 | Log( Format('-- ChangeView : %s [%d Sessions] --',[CVS.Value.ChangeViewName, CVS.Value.Count] ))
163 | else
164 | CVS.Value.GetStats(AOutput);
165 |
166 | Log( '' );
167 |
168 | end;
169 |
170 |
171 | finally
172 | AOutput.EndUpdate;
173 | end;
174 | end;
175 |
176 |
177 | procedure TChangeViewSessionManager.LeaveCriticalSection;
178 | begin
179 | FCriticalSectionManager.Leave;
180 | end;
181 |
182 | procedure TChangeViewSessionManager.Sweep(SecondsInactive: Integer);
183 | begin
184 | var FCloseList := TStringList.Create;
185 | try
186 | EnterCriticalSection;
187 | try
188 | for var FChangeViewList in FChangeViewSessionList do
189 | begin
190 | FChangeViewList.Value.CloseInactiveSession(SecondsInactive);
191 | if FChangeViewList.Value.Count = 0 then
192 | begin
193 | FCloseList.Add(FChangeViewList.Key);
194 | end;
195 | end;
196 |
197 | for var S in FCloseList do
198 | FChangeViewSessionList.Remove(S);
199 |
200 | finally
201 | LeaveCriticalSection;
202 | end;
203 |
204 | finally
205 | FCloseList.Free;
206 | end;
207 |
208 | end;
209 |
210 | { TChangeViewSessions }
211 |
212 | procedure TChangeViewSessions.CloseInactiveSession(
213 | InactiveTimeInSeconds: Integer);
214 | begin
215 | var CloseList := TStringList.Create;
216 | try
217 | EnterCriticalSection;
218 | try
219 | for var FCurrSession in FSessions do
220 | begin
221 | if FCurrSession.Value.LatestActivity.IncSecond(InactiveTimeInSeconds) < Now then
222 | begin
223 | CloseList.Add(FCurrSession.Key);
224 | end;
225 | end;
226 | finally
227 | LeaveCriticalSection;
228 | end;
229 |
230 | for var FDeviceID in CloseList do
231 | CloseSession(FDeviceID);
232 |
233 | finally
234 | CloseList.Free;
235 | end;
236 | end;
237 |
238 | procedure TChangeViewSessions.CloseSession(ADeviceID: string);
239 | begin
240 | EnterCriticalSection;
241 | try
242 | var FCurrSession := FindSession(ADeviceID);
243 | if FCurrSession <> nil then
244 | begin
245 | FSessions.Remove(ADeviceID);
246 | FCurrSession.Free;
247 | end;
248 | finally
249 | LeaveCriticalSection;
250 | end;
251 | end;
252 |
253 | constructor TChangeViewSessions.Create(AOwner: TComponent;
254 | AChangeViewName: String);
255 | begin
256 | inherited Create(AOwner);
257 | FCriticalSection := TCriticalSection.Create;
258 | FChangeViewName := AChangeViewName;
259 | FSessions := TChangeViewSessionItems.Create;
260 | end;
261 |
262 | destructor TChangeViewSessions.Destroy;
263 | begin
264 | FSessions.Free;
265 | FCriticalSection.Free;
266 | inherited;
267 | end;
268 |
269 | procedure TChangeViewSessions.EnterCriticalSection;
270 | begin
271 | FCriticalSection.Enter;
272 | end;
273 |
274 | function TChangeViewSessions.FindSession(
275 | ADeviceID: string): TChangeViewConnection;
276 | var
277 | FFoundSession : TChangeViewConnection;
278 | begin
279 | FSessions.TryGetValue(ADeviceID, FFoundSession);
280 | Result := FFoundSession;
281 | end;
282 |
283 | function TChangeViewSessions.GetCount: Integer;
284 | begin
285 | Result := FSessions.Count;
286 | end;
287 |
288 | procedure TChangeViewSessions.GetStats(AOutput: TStrings);
289 |
290 | procedure Log(s : string);
291 | begin
292 | AOutput.Add(s);
293 | end;
294 |
295 | begin
296 | AOutput.BeginUpdate;
297 | try
298 | Log( Format('-- ChangeView : %s [%d Sessions] --',[ChangeViewName, FSessions.Count] ));
299 | for var CurrSession in FSessions do begin
300 | Log( Format('Device : %s [Active %s]',[CurrSession.Value.DeviceID, DateTimeToStr(CurrSession.Value.LatestActivity)]) );
301 | Log('');
302 | end;
303 | finally
304 | AOutput.EndUpdate;
305 | end;
306 | end;
307 |
308 | procedure TChangeViewSessions.LeaveCriticalSection;
309 | begin
310 | FCriticalSection.Leave;
311 | end;
312 |
313 | function TChangeViewSessions.NewSession(
314 | ADeviceID: string): TChangeViewConnection;
315 | begin
316 | if FindSession(ADeviceID) <> nil then
317 | CloseSession(ADeviceID);
318 |
319 | var FNewSession := TChangeViewConnection.Create(Self,aDeviceID,ChangeViewName);
320 |
321 | EnterCriticalSection;
322 | try
323 | if not FSessions.TryAdd(ADeviceID, FNewSession) then
324 | FNewSession.Free;
325 | finally
326 | LeaveCriticalSection;
327 | end;
328 |
329 | // Get from list incase of issue adding
330 | Result := FindSession(ADeviceID);
331 |
332 | end;
333 |
334 | initialization
335 | FChangeViewSessionManager := TChangeViewSessionManager.Create(nil);
336 |
337 | finalization
338 | try
339 | FreeAndNil(FChangeViewSessionManager);
340 | except
341 | end;
342 |
343 |
344 |
345 | end.
346 |
--------------------------------------------------------------------------------
/Delphi/TasksExample/Simple Server/SimpleRADServerTasks.dproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | {5736511B-90F4-46CA-A073-E543F230B706}
4 | SimpleRADServerTasks.dpk
5 | 19.4
6 | None
7 | True
8 | Release
9 | Win32
10 | 131
11 | Package
12 |
13 |
14 | true
15 |
16 |
17 | true
18 | Base
19 | true
20 |
21 |
22 | true
23 | Base
24 | true
25 |
26 |
27 | true
28 | Base
29 | true
30 |
31 |
32 | true
33 | Base
34 | true
35 |
36 |
37 | true
38 | Base
39 | true
40 |
41 |
42 | true
43 | Base
44 | true
45 |
46 |
47 | true
48 | Base
49 | true
50 |
51 |
52 | true
53 | Base
54 | true
55 |
56 |
57 | true
58 | Base
59 | true
60 |
61 |
62 | true
63 | Cfg_1
64 | true
65 | true
66 |
67 |
68 | true
69 | Base
70 | true
71 |
72 |
73 | .\$(Platform)\$(Config)
74 | .\$(Platform)\$(Config)
75 | false
76 | false
77 | false
78 | false
79 | false
80 | true
81 | true
82 | System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)
83 | True
84 | -l"$(TargetName)"
85 | $(BDS)\bin\delphi_PROJECTICON.ico
86 | $(BDS)\bin\delphi_PROJECTICNS.icns
87 | SimpleRADServerTasks
88 |
89 |
90 | package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey=
91 | Debug
92 | annotation-1.2.0.dex.jar;asynclayoutinflater-1.0.0.dex.jar;billing-4.0.0.dex.jar;browser-1.0.0.dex.jar;cloud-messaging.dex.jar;collection-1.0.0.dex.jar;coordinatorlayout-1.0.0.dex.jar;core-1.5.0-rc02.dex.jar;core-common-2.0.1.dex.jar;core-runtime-2.0.1.dex.jar;cursoradapter-1.0.0.dex.jar;customview-1.0.0.dex.jar;documentfile-1.0.0.dex.jar;drawerlayout-1.0.0.dex.jar;firebase-annotations-16.0.0.dex.jar;firebase-common-20.0.0.dex.jar;firebase-components-17.0.0.dex.jar;firebase-datatransport-18.0.0.dex.jar;firebase-encoders-17.0.0.dex.jar;firebase-encoders-json-18.0.0.dex.jar;firebase-iid-interop-17.1.0.dex.jar;firebase-installations-17.0.0.dex.jar;firebase-installations-interop-17.0.0.dex.jar;firebase-measurement-connector-19.0.0.dex.jar;firebase-messaging-22.0.0.dex.jar;fmx.dex.jar;fragment-1.0.0.dex.jar;google-play-licensing.dex.jar;interpolator-1.0.0.dex.jar;javax.inject-1.dex.jar;legacy-support-core-ui-1.0.0.dex.jar;legacy-support-core-utils-1.0.0.dex.jar;lifecycle-common-2.0.0.dex.jar;lifecycle-livedata-2.0.0.dex.jar;lifecycle-livedata-core-2.0.0.dex.jar;lifecycle-runtime-2.0.0.dex.jar;lifecycle-service-2.0.0.dex.jar;lifecycle-viewmodel-2.0.0.dex.jar;listenablefuture-1.0.dex.jar;loader-1.0.0.dex.jar;localbroadcastmanager-1.0.0.dex.jar;play-services-ads-20.1.0.dex.jar;play-services-ads-base-20.1.0.dex.jar;play-services-ads-identifier-17.0.0.dex.jar;play-services-ads-lite-20.1.0.dex.jar;play-services-base-17.5.0.dex.jar;play-services-basement-17.6.0.dex.jar;play-services-cloud-messaging-16.0.0.dex.jar;play-services-drive-17.0.0.dex.jar;play-services-games-21.0.0.dex.jar;play-services-location-18.0.0.dex.jar;play-services-maps-17.0.1.dex.jar;play-services-measurement-base-18.0.0.dex.jar;play-services-measurement-sdk-api-18.0.0.dex.jar;play-services-places-placereport-17.0.0.dex.jar;play-services-stats-17.0.0.dex.jar;play-services-tasks-17.2.0.dex.jar;print-1.0.0.dex.jar;room-common-2.1.0.dex.jar;room-runtime-2.1.0.dex.jar;slidingpanelayout-1.0.0.dex.jar;sqlite-2.0.1.dex.jar;sqlite-framework-2.0.1.dex.jar;swiperefreshlayout-1.0.0.dex.jar;transport-api-3.0.0.dex.jar;transport-backend-cct-3.0.0.dex.jar;transport-runtime-3.0.0.dex.jar;user-messaging-platform-1.0.0.dex.jar;versionedparcelable-1.1.1.dex.jar;viewpager-1.0.0.dex.jar;work-runtime-2.1.0.dex.jar
93 |
94 |
95 | package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey=
96 | Debug
97 | annotation-1.2.0.dex.jar;asynclayoutinflater-1.0.0.dex.jar;billing-4.0.0.dex.jar;browser-1.0.0.dex.jar;cloud-messaging.dex.jar;collection-1.0.0.dex.jar;coordinatorlayout-1.0.0.dex.jar;core-1.5.0-rc02.dex.jar;core-common-2.0.1.dex.jar;core-runtime-2.0.1.dex.jar;cursoradapter-1.0.0.dex.jar;customview-1.0.0.dex.jar;documentfile-1.0.0.dex.jar;drawerlayout-1.0.0.dex.jar;firebase-annotations-16.0.0.dex.jar;firebase-common-20.0.0.dex.jar;firebase-components-17.0.0.dex.jar;firebase-datatransport-18.0.0.dex.jar;firebase-encoders-17.0.0.dex.jar;firebase-encoders-json-18.0.0.dex.jar;firebase-iid-interop-17.1.0.dex.jar;firebase-installations-17.0.0.dex.jar;firebase-installations-interop-17.0.0.dex.jar;firebase-measurement-connector-19.0.0.dex.jar;firebase-messaging-22.0.0.dex.jar;fmx.dex.jar;fragment-1.0.0.dex.jar;google-play-licensing.dex.jar;interpolator-1.0.0.dex.jar;javax.inject-1.dex.jar;legacy-support-core-ui-1.0.0.dex.jar;legacy-support-core-utils-1.0.0.dex.jar;lifecycle-common-2.0.0.dex.jar;lifecycle-livedata-2.0.0.dex.jar;lifecycle-livedata-core-2.0.0.dex.jar;lifecycle-runtime-2.0.0.dex.jar;lifecycle-service-2.0.0.dex.jar;lifecycle-viewmodel-2.0.0.dex.jar;listenablefuture-1.0.dex.jar;loader-1.0.0.dex.jar;localbroadcastmanager-1.0.0.dex.jar;play-services-ads-20.1.0.dex.jar;play-services-ads-base-20.1.0.dex.jar;play-services-ads-identifier-17.0.0.dex.jar;play-services-ads-lite-20.1.0.dex.jar;play-services-base-17.5.0.dex.jar;play-services-basement-17.6.0.dex.jar;play-services-cloud-messaging-16.0.0.dex.jar;play-services-drive-17.0.0.dex.jar;play-services-games-21.0.0.dex.jar;play-services-location-18.0.0.dex.jar;play-services-maps-17.0.1.dex.jar;play-services-measurement-base-18.0.0.dex.jar;play-services-measurement-sdk-api-18.0.0.dex.jar;play-services-places-placereport-17.0.0.dex.jar;play-services-stats-17.0.0.dex.jar;play-services-tasks-17.2.0.dex.jar;print-1.0.0.dex.jar;room-common-2.1.0.dex.jar;room-runtime-2.1.0.dex.jar;slidingpanelayout-1.0.0.dex.jar;sqlite-2.0.1.dex.jar;sqlite-framework-2.0.1.dex.jar;swiperefreshlayout-1.0.0.dex.jar;transport-api-3.0.0.dex.jar;transport-backend-cct-3.0.0.dex.jar;transport-runtime-3.0.0.dex.jar;user-messaging-platform-1.0.0.dex.jar;versionedparcelable-1.1.1.dex.jar;viewpager-1.0.0.dex.jar;work-runtime-2.1.0.dex.jar
98 |
99 |
100 | CFBundleName=$(MSBuildProjectName);CFBundleDevelopmentRegion=en;CFBundleDisplayName=$(MSBuildProjectName);CFBundleIdentifier=$(MSBuildProjectName);CFBundleInfoDictionaryVersion=7.1;CFBundleVersion=1.0.0;CFBundleShortVersionString=1.0.0;CFBundlePackageType=APPL;CFBundleSignature=????;LSRequiresIPhoneOS=true;CFBundleAllowMixedLocalizations=YES;CFBundleExecutable=$(MSBuildProjectName);UIDeviceFamily=iPhone & iPad;NSLocationAlwaysUsageDescription=The reason for accessing the location information of the user;NSLocationWhenInUseUsageDescription=The reason for accessing the location information of the user;NSLocationAlwaysAndWhenInUseUsageDescription=The reason for accessing the location information of the user;UIBackgroundModes=;NSContactsUsageDescription=The reason for accessing the contacts;NSPhotoLibraryUsageDescription=The reason for accessing the photo library;NSPhotoLibraryAddUsageDescription=The reason for adding to the photo library;NSCameraUsageDescription=The reason for accessing the camera;NSFaceIDUsageDescription=The reason for accessing the face id;NSMicrophoneUsageDescription=The reason for accessing the microphone;NSSiriUsageDescription=The reason for accessing Siri;ITSAppUsesNonExemptEncryption=false;NSBluetoothAlwaysUsageDescription=The reason for accessing bluetooth;NSBluetoothPeripheralUsageDescription=The reason for accessing bluetooth peripherals;NSCalendarsUsageDescription=The reason for accessing the calendar data;NSRemindersUsageDescription=The reason for accessing the reminders;NSMotionUsageDescription=The reason for accessing the accelerometer;NSSpeechRecognitionUsageDescription=The reason for requesting to send user data to Apple's speech recognition servers
101 | iPhoneAndiPad
102 | true
103 | Debug
104 | $(MSBuildProjectName)
105 |
106 |
107 | /usr/lib/ems/EMSDevServerCommand
108 |
109 |
110 | CFBundleName=$(MSBuildProjectName);CFBundleDisplayName=$(MSBuildProjectName);CFBundleIdentifier=$(MSBuildProjectName);CFBundleVersion=1.0.0;CFBundleShortVersionString=1.0.0;CFBundlePackageType=APPL;CFBundleSignature=????;CFBundleAllowMixedLocalizations=YES;CFBundleExecutable=$(MSBuildProjectName);NSHighResolutionCapable=true;LSApplicationCategoryType=public.app-category.utilities;NSLocationUsageDescription=The reason for accessing the location information of the user;NSContactsUsageDescription=The reason for accessing the contacts;NSCalendarsUsageDescription=The reason for accessing the calendar data;NSRemindersUsageDescription=The reason for accessing the reminders;NSCameraUsageDescription=The reason for accessing the camera;NSMicrophoneUsageDescription=The reason for accessing the microphone;NSMotionUsageDescription=The reason for accessing the accelerometer;NSDesktopFolderUsageDescription=The reason for accessing the Desktop folder;NSDocumentsFolderUsageDescription=The reason for accessing the Documents folder;NSDownloadsFolderUsageDescription=The reason for accessing the Downloads folder;NSNetworkVolumesUsageDescription=The reason for accessing files on a network volume;NSRemovableVolumesUsageDescription=The reason for accessing files on a removable volume;NSSpeechRecognitionUsageDescription=The reason for requesting to send user data to Apple's speech recognition servers
111 | Debug
112 |
113 |
114 | CFBundleName=$(MSBuildProjectName);CFBundleDisplayName=$(MSBuildProjectName);CFBundleIdentifier=$(MSBuildProjectName);CFBundleVersion=1.0.0;CFBundleShortVersionString=1.0.0;CFBundlePackageType=APPL;CFBundleSignature=????;CFBundleAllowMixedLocalizations=YES;CFBundleExecutable=$(MSBuildProjectName);NSHighResolutionCapable=true;LSApplicationCategoryType=public.app-category.utilities;NSLocationUsageDescription=The reason for accessing the location information of the user;NSContactsUsageDescription=The reason for accessing the contacts;NSCalendarsUsageDescription=The reason for accessing the calendar data;NSRemindersUsageDescription=The reason for accessing the reminders;NSCameraUsageDescription=The reason for accessing the camera;NSMicrophoneUsageDescription=The reason for accessing the microphone;NSMotionUsageDescription=The reason for accessing the accelerometer;NSDesktopFolderUsageDescription=The reason for accessing the Desktop folder;NSDocumentsFolderUsageDescription=The reason for accessing the Documents folder;NSDownloadsFolderUsageDescription=The reason for accessing the Downloads folder;NSNetworkVolumesUsageDescription=The reason for accessing files on a network volume;NSRemovableVolumesUsageDescription=The reason for accessing files on a removable volume;NSSpeechRecognitionUsageDescription=The reason for requesting to send user data to Apple's speech recognition servers
115 | Debug
116 |
117 |
118 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
119 | Debug
120 | true
121 | CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
122 | 1033
123 | $(BDS)\bin\EMSDevServer.exe
124 |
125 |
126 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace)
127 | Debug
128 | true
129 | CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
130 | 1033
131 | $(BDS)\bin64\EMSDevServer.exe
132 |
133 |
134 | DEBUG;$(DCC_Define)
135 | true
136 | false
137 | true
138 | true
139 | true
140 | true
141 | true
142 |
143 |
144 | false
145 |
146 |
147 | false
148 | RELEASE;$(DCC_Define)
149 | 0
150 | 0
151 |
152 |
153 |
154 | MainSource
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 | dfm
167 | TDataModule
168 |
169 |
170 | Base
171 |
172 |
173 | Cfg_1
174 | Base
175 |
176 |
177 | Cfg_2
178 | Base
179 |
180 |
181 |
182 | Delphi.Personality.12
183 | Package
184 |
185 |
186 |
187 | SimpleRADServerTasks.dpk
188 |
189 |
190 |
191 |
192 |
193 | true
194 |
195 |
196 |
197 |
198 | true
199 |
200 |
201 |
202 |
203 | true
204 |
205 |
206 |
207 |
208 | SimpleRADServerTasks.bpl
209 | true
210 |
211 |
212 |
213 |
214 | 1
215 |
216 |
217 | 0
218 |
219 |
220 |
221 |
222 | classes
223 | 64
224 |
225 |
226 | classes
227 | 64
228 |
229 |
230 |
231 |
232 | res\xml
233 | 1
234 |
235 |
236 | res\xml
237 | 1
238 |
239 |
240 |
241 |
242 | library\lib\armeabi-v7a
243 | 1
244 |
245 |
246 |
247 |
248 | library\lib\armeabi
249 | 1
250 |
251 |
252 | library\lib\armeabi
253 | 1
254 |
255 |
256 |
257 |
258 | library\lib\armeabi-v7a
259 | 1
260 |
261 |
262 |
263 |
264 | library\lib\mips
265 | 1
266 |
267 |
268 | library\lib\mips
269 | 1
270 |
271 |
272 |
273 |
274 | library\lib\armeabi-v7a
275 | 1
276 |
277 |
278 | library\lib\arm64-v8a
279 | 1
280 |
281 |
282 |
283 |
284 | library\lib\armeabi-v7a
285 | 1
286 |
287 |
288 |
289 |
290 | res\drawable
291 | 1
292 |
293 |
294 | res\drawable
295 | 1
296 |
297 |
298 |
299 |
300 | res\values
301 | 1
302 |
303 |
304 | res\values
305 | 1
306 |
307 |
308 |
309 |
310 | res\values-v21
311 | 1
312 |
313 |
314 | res\values-v21
315 | 1
316 |
317 |
318 |
319 |
320 | res\values
321 | 1
322 |
323 |
324 | res\values
325 | 1
326 |
327 |
328 |
329 |
330 | res\drawable
331 | 1
332 |
333 |
334 | res\drawable
335 | 1
336 |
337 |
338 |
339 |
340 | res\drawable-xxhdpi
341 | 1
342 |
343 |
344 | res\drawable-xxhdpi
345 | 1
346 |
347 |
348 |
349 |
350 | res\drawable-xxxhdpi
351 | 1
352 |
353 |
354 | res\drawable-xxxhdpi
355 | 1
356 |
357 |
358 |
359 |
360 | res\drawable-ldpi
361 | 1
362 |
363 |
364 | res\drawable-ldpi
365 | 1
366 |
367 |
368 |
369 |
370 | res\drawable-mdpi
371 | 1
372 |
373 |
374 | res\drawable-mdpi
375 | 1
376 |
377 |
378 |
379 |
380 | res\drawable-hdpi
381 | 1
382 |
383 |
384 | res\drawable-hdpi
385 | 1
386 |
387 |
388 |
389 |
390 | res\drawable-xhdpi
391 | 1
392 |
393 |
394 | res\drawable-xhdpi
395 | 1
396 |
397 |
398 |
399 |
400 | res\drawable-mdpi
401 | 1
402 |
403 |
404 | res\drawable-mdpi
405 | 1
406 |
407 |
408 |
409 |
410 | res\drawable-hdpi
411 | 1
412 |
413 |
414 | res\drawable-hdpi
415 | 1
416 |
417 |
418 |
419 |
420 | res\drawable-xhdpi
421 | 1
422 |
423 |
424 | res\drawable-xhdpi
425 | 1
426 |
427 |
428 |
429 |
430 | res\drawable-xxhdpi
431 | 1
432 |
433 |
434 | res\drawable-xxhdpi
435 | 1
436 |
437 |
438 |
439 |
440 | res\drawable-xxxhdpi
441 | 1
442 |
443 |
444 | res\drawable-xxxhdpi
445 | 1
446 |
447 |
448 |
449 |
450 | res\drawable-small
451 | 1
452 |
453 |
454 | res\drawable-small
455 | 1
456 |
457 |
458 |
459 |
460 | res\drawable-normal
461 | 1
462 |
463 |
464 | res\drawable-normal
465 | 1
466 |
467 |
468 |
469 |
470 | res\drawable-large
471 | 1
472 |
473 |
474 | res\drawable-large
475 | 1
476 |
477 |
478 |
479 |
480 | res\drawable-xlarge
481 | 1
482 |
483 |
484 | res\drawable-xlarge
485 | 1
486 |
487 |
488 |
489 |
490 | res\values
491 | 1
492 |
493 |
494 | res\values
495 | 1
496 |
497 |
498 |
499 |
500 | 1
501 |
502 |
503 | 1
504 |
505 |
506 | 0
507 |
508 |
509 |
510 |
511 | 1
512 | .framework
513 |
514 |
515 | 1
516 | .framework
517 |
518 |
519 | 1
520 | .framework
521 |
522 |
523 | 0
524 |
525 |
526 |
527 |
528 | 1
529 | .dylib
530 |
531 |
532 | 1
533 | .dylib
534 |
535 |
536 | 1
537 | .dylib
538 |
539 |
540 | 0
541 | .dll;.bpl
542 |
543 |
544 |
545 |
546 | 1
547 | .dylib
548 |
549 |
550 | 1
551 | .dylib
552 |
553 |
554 | 1
555 | .dylib
556 |
557 |
558 | 1
559 | .dylib
560 |
561 |
562 | 1
563 | .dylib
564 |
565 |
566 | 1
567 | .dylib
568 |
569 |
570 | 0
571 | .bpl
572 |
573 |
574 |
575 |
576 | 0
577 |
578 |
579 | 0
580 |
581 |
582 | 0
583 |
584 |
585 | 0
586 |
587 |
588 | 0
589 |
590 |
591 | 0
592 |
593 |
594 | 0
595 |
596 |
597 | 0
598 |
599 |
600 | 0
601 |
602 |
603 |
604 |
605 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
606 | 1
607 |
608 |
609 |
610 |
611 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
612 | 1
613 |
614 |
615 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
616 | 1
617 |
618 |
619 |
620 |
621 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
622 | 1
623 |
624 |
625 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
626 | 1
627 |
628 |
629 |
630 |
631 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
632 | 1
633 |
634 |
635 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
636 | 1
637 |
638 |
639 |
640 |
641 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
642 | 1
643 |
644 |
645 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
646 | 1
647 |
648 |
649 |
650 |
651 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
652 | 1
653 |
654 |
655 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
656 | 1
657 |
658 |
659 |
660 |
661 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
662 | 1
663 |
664 |
665 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
666 | 1
667 |
668 |
669 |
670 |
671 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
672 | 1
673 |
674 |
675 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
676 | 1
677 |
678 |
679 |
680 |
681 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
682 | 1
683 |
684 |
685 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
686 | 1
687 |
688 |
689 |
690 |
691 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
692 | 1
693 |
694 |
695 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
696 | 1
697 |
698 |
699 |
700 |
701 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
702 | 1
703 |
704 |
705 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
706 | 1
707 |
708 |
709 |
710 |
711 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
712 | 1
713 |
714 |
715 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
716 | 1
717 |
718 |
719 |
720 |
721 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
722 | 1
723 |
724 |
725 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
726 | 1
727 |
728 |
729 |
730 |
731 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
732 | 1
733 |
734 |
735 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
736 | 1
737 |
738 |
739 |
740 |
741 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
742 | 1
743 |
744 |
745 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
746 | 1
747 |
748 |
749 |
750 |
751 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
752 | 1
753 |
754 |
755 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
756 | 1
757 |
758 |
759 |
760 |
761 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
762 | 1
763 |
764 |
765 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
766 | 1
767 |
768 |
769 |
770 |
771 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
772 | 1
773 |
774 |
775 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
776 | 1
777 |
778 |
779 |
780 |
781 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
782 | 1
783 |
784 |
785 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
786 | 1
787 |
788 |
789 |
790 |
791 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
792 | 1
793 |
794 |
795 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
796 | 1
797 |
798 |
799 |
800 |
801 | 1
802 |
803 |
804 | 1
805 |
806 |
807 |
808 |
809 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
810 | 1
811 |
812 |
813 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
814 | 1
815 |
816 |
817 |
818 |
819 |
820 |
821 |
822 | 1
823 |
824 |
825 | 1
826 |
827 |
828 | 1
829 |
830 |
831 |
832 |
833 |
834 |
835 |
836 | Contents\Resources
837 | 1
838 |
839 |
840 | Contents\Resources
841 | 1
842 |
843 |
844 | Contents\Resources
845 | 1
846 |
847 |
848 |
849 |
850 | library\lib\armeabi-v7a
851 | 1
852 |
853 |
854 | library\lib\arm64-v8a
855 | 1
856 |
857 |
858 | 1
859 |
860 |
861 | 1
862 |
863 |
864 | 1
865 |
866 |
867 | 1
868 |
869 |
870 | 1
871 |
872 |
873 | 1
874 |
875 |
876 | 1
877 |
878 |
879 | 0
880 |
881 |
882 |
883 |
884 | library\lib\armeabi-v7a
885 | 1
886 |
887 |
888 |
889 |
890 | 1
891 |
892 |
893 | 1
894 |
895 |
896 |
897 |
898 | Assets
899 | 1
900 |
901 |
902 | Assets
903 | 1
904 |
905 |
906 |
907 |
908 | Assets
909 | 1
910 |
911 |
912 | Assets
913 | 1
914 |
915 |
916 |
917 |
918 |
919 |
920 |
921 |
922 |
923 |
924 |
925 |
926 |
927 |
928 |
929 | False
930 | False
931 | False
932 | True
933 | False
934 | False
935 | True
936 | True
937 |
938 |
939 | 12
940 |
941 |
942 |
943 |
944 |
945 |
--------------------------------------------------------------------------------
/Delphi/ChangeViews/Client/ChangeViewsEMSThingPoint.dproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | {AE2CE7DA-D701-4FDB-8C97-06EE8521522C}
4 | 20.3
5 | VCL
6 | True
7 | Debug
8 | Win32
9 | ChangeViewsEMSThingPoint
10 | 3
11 | Application
12 | ChangeViewsEMSThingPoint.dpr
13 |
14 |
15 | true
16 |
17 |
18 | true
19 | Base
20 | true
21 |
22 |
23 | true
24 | Base
25 | true
26 |
27 |
28 | true
29 | Base
30 | true
31 |
32 |
33 | true
34 | Cfg_1
35 | true
36 | true
37 |
38 |
39 | true
40 | Cfg_1
41 | true
42 | true
43 |
44 |
45 | true
46 | Base
47 | true
48 |
49 |
50 | true
51 | Cfg_2
52 | true
53 | true
54 |
55 |
56 | true
57 | Cfg_2
58 | true
59 | true
60 |
61 |
62 | .\$(Platform)\$(Config)
63 | .\$(Platform)\$(Config)
64 | false
65 | false
66 | false
67 | false
68 | false
69 | System;Xml;Data;Datasnap;Web;Soap;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;$(DCC_Namespace)
70 | $(BDS)\bin\delphi_PROJECTICON.ico
71 | $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
72 | $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
73 | ChangeViewsEMSThingPoint
74 |
75 |
76 | vclwinx;DataSnapServer;fmx;emshosting;vclie;DbxCommonDriver;bindengine;IndyIPCommon;VCLRESTComponents;DBXMSSQLDriver;FireDACCommonODBC;emsclient;FireDACCommonDriver;appanalytics;IndyProtocols;vclx;Skia.Package.RTL;IndyIPClient;dbxcds;vcledge;bindcompvclwinx;FmxTeeUI;emsedge;bindcompfmx;DBXFirebirdDriver;inetdb;FireDACSqliteDriver;DbxClientDriver;FireDACASADriver;Tee;soapmidas;vclactnband;TeeUI;fmxFireDAC;dbexpress;FireDACInfxDriver;DBXMySQLDriver;VclSmp;inet;DataSnapCommon;vcltouch;fmxase;DBXOdbcDriver;dbrtl;FireDACDBXDriver;Skia.Package.FMX;FireDACOracleDriver;fmxdae;TeeDB;FireDACMSAccDriver;CustomIPTransport;FireDACMSSQLDriver;DataSnapIndy10ServerTransport;DataSnapConnectors;vcldsnap;DBXInterBaseDriver;FireDACMongoDBDriver;IndySystem;FireDACTDataDriver;Skia.Package.VCL;vcldb;vclFireDAC;bindcomp;FireDACCommon;DataSnapServerMidas;FireDACODBCDriver;emsserverresource;IndyCore;RESTBackendComponents;bindcompdbx;rtl;FireDACMySQLDriver;FireDACADSDriver;RESTComponents;DBXSqliteDriver;vcl;IndyIPServer;dsnapxml;dsnapcon;DataSnapClient;DataSnapProviderClient;adortl;DBXSybaseASEDriver;DBXDb2Driver;vclimg;DataSnapFireDAC;emsclientfiredac;FireDACPgDriver;FireDAC;FireDACDSDriver;inetdbxpress;xmlrtl;tethering;bindcompvcl;dsnap;CloudService;DBXSybaseASADriver;DBXOracleDriver;FireDACDb2Driver;DBXInformixDriver;fmxobj;bindcompvclsmp;FMXTee;DataSnapNativeClient;DatasnapConnectorsFreePascal;soaprtl;soapserver;FireDACIBDriver;$(DCC_UsePackage)
77 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
78 | Debug
79 | true
80 | CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
81 | 1033
82 | $(BDS)\bin\default_app.manifest
83 |
84 |
85 | vclwinx;DataSnapServer;fmx;emshosting;vclie;DbxCommonDriver;bindengine;IndyIPCommon;VCLRESTComponents;DBXMSSQLDriver;FireDACCommonODBC;emsclient;FireDACCommonDriver;appanalytics;IndyProtocols;vclx;IndyIPClient;dbxcds;vcledge;bindcompvclwinx;FmxTeeUI;emsedge;bindcompfmx;DBXFirebirdDriver;inetdb;FireDACSqliteDriver;DbxClientDriver;FireDACASADriver;Tee;soapmidas;vclactnband;TeeUI;fmxFireDAC;dbexpress;FireDACInfxDriver;DBXMySQLDriver;VclSmp;inet;DataSnapCommon;vcltouch;fmxase;DBXOdbcDriver;dbrtl;FireDACDBXDriver;FireDACOracleDriver;fmxdae;TeeDB;FireDACMSAccDriver;CustomIPTransport;FireDACMSSQLDriver;DataSnapIndy10ServerTransport;DataSnapConnectors;vcldsnap;DBXInterBaseDriver;FireDACMongoDBDriver;IndySystem;FireDACTDataDriver;Skia.Package.VCL;vcldb;vclFireDAC;bindcomp;FireDACCommon;DataSnapServerMidas;FireDACODBCDriver;emsserverresource;IndyCore;RESTBackendComponents;bindcompdbx;rtl;FireDACMySQLDriver;FireDACADSDriver;RESTComponents;DBXSqliteDriver;vcl;IndyIPServer;dsnapxml;dsnapcon;DataSnapClient;DataSnapProviderClient;adortl;DBXSybaseASEDriver;DBXDb2Driver;vclimg;DataSnapFireDAC;emsclientfiredac;FireDACPgDriver;FireDAC;FireDACDSDriver;inetdbxpress;xmlrtl;tethering;bindcompvcl;dsnap;CloudService;DBXSybaseASADriver;DBXOracleDriver;FireDACDb2Driver;DBXInformixDriver;fmxobj;bindcompvclsmp;FMXTee;DataSnapNativeClient;DatasnapConnectorsFreePascal;soaprtl;soapserver;FireDACIBDriver;$(DCC_UsePackage)
86 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace)
87 | Debug
88 | true
89 | CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
90 | 1033
91 | $(BDS)\bin\default_app.manifest
92 |
93 |
94 | DEBUG;$(DCC_Define)
95 | true
96 | false
97 | true
98 | true
99 | true
100 | true
101 | true
102 |
103 |
104 | false
105 | PerMonitorV2
106 |
107 |
108 | PerMonitorV2
109 |
110 |
111 | false
112 | RELEASE;$(DCC_Define)
113 | 0
114 | 0
115 |
116 |
117 | PerMonitorV2
118 |
119 |
120 | PerMonitorV2
121 |
122 |
123 |
124 | MainSource
125 |
126 |
127 |
128 | dfm
129 |
130 |
131 |
132 |
133 | dfm
134 | TDataModule
135 |
136 |
137 |
138 | dfm
139 | TDataModule
140 |
141 |
142 |
143 | Base
144 |
145 |
146 | Cfg_1
147 | Base
148 |
149 |
150 | Cfg_2
151 | Base
152 |
153 |
154 |
155 | Delphi.Personality.12
156 | Application
157 |
158 |
159 |
160 | ChangeViewsEMSThingPoint.dpr
161 |
162 |
163 |
164 |
165 |
166 | ChangeViewsEMSThingPoint.exe
167 | true
168 |
169 |
170 |
171 |
172 | 1
173 |
174 |
175 | Contents\MacOS
176 | 1
177 |
178 |
179 | 0
180 |
181 |
182 |
183 |
184 | res\xml
185 | 1
186 |
187 |
188 | res\xml
189 | 1
190 |
191 |
192 |
193 |
194 | library\lib\armeabi
195 | 1
196 |
197 |
198 | library\lib\armeabi
199 | 1
200 |
201 |
202 |
203 |
204 | library\lib\armeabi-v7a
205 | 1
206 |
207 |
208 |
209 |
210 | library\lib\mips
211 | 1
212 |
213 |
214 | library\lib\mips
215 | 1
216 |
217 |
218 |
219 |
220 | library\lib\armeabi-v7a
221 | 1
222 |
223 |
224 | library\lib\arm64-v8a
225 | 1
226 |
227 |
228 |
229 |
230 | library\lib\armeabi-v7a
231 | 1
232 |
233 |
234 |
235 |
236 | res\drawable
237 | 1
238 |
239 |
240 | res\drawable
241 | 1
242 |
243 |
244 |
245 |
246 | res\drawable-anydpi-v21
247 | 1
248 |
249 |
250 | res\drawable-anydpi-v21
251 | 1
252 |
253 |
254 |
255 |
256 | res\values
257 | 1
258 |
259 |
260 | res\values
261 | 1
262 |
263 |
264 |
265 |
266 | res\values-v21
267 | 1
268 |
269 |
270 | res\values-v21
271 | 1
272 |
273 |
274 |
275 |
276 | res\values-v31
277 | 1
278 |
279 |
280 | res\values-v31
281 | 1
282 |
283 |
284 |
285 |
286 | res\values-v35
287 | 1
288 |
289 |
290 | res\values-v35
291 | 1
292 |
293 |
294 |
295 |
296 | res\drawable-anydpi-v26
297 | 1
298 |
299 |
300 | res\drawable-anydpi-v26
301 | 1
302 |
303 |
304 |
305 |
306 | res\drawable
307 | 1
308 |
309 |
310 | res\drawable
311 | 1
312 |
313 |
314 |
315 |
316 | res\drawable
317 | 1
318 |
319 |
320 | res\drawable
321 | 1
322 |
323 |
324 |
325 |
326 | res\drawable
327 | 1
328 |
329 |
330 | res\drawable
331 | 1
332 |
333 |
334 |
335 |
336 | res\drawable-anydpi-v33
337 | 1
338 |
339 |
340 | res\drawable-anydpi-v33
341 | 1
342 |
343 |
344 |
345 |
346 | res\values
347 | 1
348 |
349 |
350 | res\values
351 | 1
352 |
353 |
354 |
355 |
356 | res\values-night-v21
357 | 1
358 |
359 |
360 | res\values-night-v21
361 | 1
362 |
363 |
364 |
365 |
366 | res\drawable
367 | 1
368 |
369 |
370 | res\drawable
371 | 1
372 |
373 |
374 |
375 |
376 | res\drawable-xxhdpi
377 | 1
378 |
379 |
380 | res\drawable-xxhdpi
381 | 1
382 |
383 |
384 |
385 |
386 | res\drawable-xxxhdpi
387 | 1
388 |
389 |
390 | res\drawable-xxxhdpi
391 | 1
392 |
393 |
394 |
395 |
396 | res\drawable-ldpi
397 | 1
398 |
399 |
400 | res\drawable-ldpi
401 | 1
402 |
403 |
404 |
405 |
406 | res\drawable-mdpi
407 | 1
408 |
409 |
410 | res\drawable-mdpi
411 | 1
412 |
413 |
414 |
415 |
416 | res\drawable-hdpi
417 | 1
418 |
419 |
420 | res\drawable-hdpi
421 | 1
422 |
423 |
424 |
425 |
426 | res\drawable-xhdpi
427 | 1
428 |
429 |
430 | res\drawable-xhdpi
431 | 1
432 |
433 |
434 |
435 |
436 | res\drawable-mdpi
437 | 1
438 |
439 |
440 | res\drawable-mdpi
441 | 1
442 |
443 |
444 |
445 |
446 | res\drawable-hdpi
447 | 1
448 |
449 |
450 | res\drawable-hdpi
451 | 1
452 |
453 |
454 |
455 |
456 | res\drawable-xhdpi
457 | 1
458 |
459 |
460 | res\drawable-xhdpi
461 | 1
462 |
463 |
464 |
465 |
466 | res\drawable-xxhdpi
467 | 1
468 |
469 |
470 | res\drawable-xxhdpi
471 | 1
472 |
473 |
474 |
475 |
476 | res\drawable-xxxhdpi
477 | 1
478 |
479 |
480 | res\drawable-xxxhdpi
481 | 1
482 |
483 |
484 |
485 |
486 | res\drawable-small
487 | 1
488 |
489 |
490 | res\drawable-small
491 | 1
492 |
493 |
494 |
495 |
496 | res\drawable-normal
497 | 1
498 |
499 |
500 | res\drawable-normal
501 | 1
502 |
503 |
504 |
505 |
506 | res\drawable-large
507 | 1
508 |
509 |
510 | res\drawable-large
511 | 1
512 |
513 |
514 |
515 |
516 | res\drawable-xlarge
517 | 1
518 |
519 |
520 | res\drawable-xlarge
521 | 1
522 |
523 |
524 |
525 |
526 | res\values
527 | 1
528 |
529 |
530 | res\values
531 | 1
532 |
533 |
534 |
535 |
536 | res\drawable-anydpi-v24
537 | 1
538 |
539 |
540 | res\drawable-anydpi-v24
541 | 1
542 |
543 |
544 |
545 |
546 | res\drawable
547 | 1
548 |
549 |
550 | res\drawable
551 | 1
552 |
553 |
554 |
555 |
556 | res\drawable-night-anydpi-v21
557 | 1
558 |
559 |
560 | res\drawable-night-anydpi-v21
561 | 1
562 |
563 |
564 |
565 |
566 | res\drawable-anydpi-v31
567 | 1
568 |
569 |
570 | res\drawable-anydpi-v31
571 | 1
572 |
573 |
574 |
575 |
576 | res\drawable-night-anydpi-v31
577 | 1
578 |
579 |
580 | res\drawable-night-anydpi-v31
581 | 1
582 |
583 |
584 |
585 |
586 | 1
587 |
588 |
589 | Contents\MacOS
590 | 1
591 |
592 |
593 | 0
594 |
595 |
596 |
597 |
598 | Contents\MacOS
599 | 1
600 | .framework
601 |
602 |
603 | Contents\MacOS
604 | 1
605 | .framework
606 |
607 |
608 | Contents\MacOS
609 | 1
610 | .framework
611 |
612 |
613 | 0
614 |
615 |
616 |
617 |
618 | 1
619 | .dylib
620 |
621 |
622 | 1
623 | .dylib
624 |
625 |
626 | 1
627 | .dylib
628 |
629 |
630 | Contents\MacOS
631 | 1
632 | .dylib
633 |
634 |
635 | Contents\MacOS
636 | 1
637 | .dylib
638 |
639 |
640 | Contents\MacOS
641 | 1
642 | .dylib
643 |
644 |
645 | 0
646 | .dll;.bpl
647 |
648 |
649 |
650 |
651 | 1
652 | .dylib
653 |
654 |
655 | 1
656 | .dylib
657 |
658 |
659 | 1
660 | .dylib
661 |
662 |
663 | Contents\MacOS
664 | 1
665 | .dylib
666 |
667 |
668 | Contents\MacOS
669 | 1
670 | .dylib
671 |
672 |
673 | Contents\MacOS
674 | 1
675 | .dylib
676 |
677 |
678 | 0
679 | .bpl
680 |
681 |
682 |
683 |
684 | 0
685 |
686 |
687 | 0
688 |
689 |
690 | 0
691 |
692 |
693 | 0
694 |
695 |
696 | 0
697 |
698 |
699 | Contents\Resources\StartUp\
700 | 0
701 |
702 |
703 | Contents\Resources\StartUp\
704 | 0
705 |
706 |
707 | Contents\Resources\StartUp\
708 | 0
709 |
710 |
711 | 0
712 |
713 |
714 |
715 |
716 | 1
717 |
718 |
719 | 1
720 |
721 |
722 |
723 |
724 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
725 | 1
726 |
727 |
728 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
729 | 1
730 |
731 |
732 |
733 |
734 | ..\
735 | 1
736 |
737 |
738 | ..\
739 | 1
740 |
741 |
742 | ..\
743 | 1
744 |
745 |
746 |
747 |
748 | Contents
749 | 1
750 |
751 |
752 | Contents
753 | 1
754 |
755 |
756 | Contents
757 | 1
758 |
759 |
760 |
761 |
762 | Contents\Resources
763 | 1
764 |
765 |
766 | Contents\Resources
767 | 1
768 |
769 |
770 | Contents\Resources
771 | 1
772 |
773 |
774 |
775 |
776 | library\lib\armeabi-v7a
777 | 1
778 |
779 |
780 | library\lib\arm64-v8a
781 | 1
782 |
783 |
784 | 1
785 |
786 |
787 | 1
788 |
789 |
790 | 1
791 |
792 |
793 | 1
794 |
795 |
796 | Contents\MacOS
797 | 1
798 |
799 |
800 | Contents\MacOS
801 | 1
802 |
803 |
804 | Contents\MacOS
805 | 1
806 |
807 |
808 | 0
809 |
810 |
811 |
812 |
813 | library\lib\armeabi-v7a
814 | 1
815 |
816 |
817 |
818 |
819 | 1
820 |
821 |
822 | 1
823 |
824 |
825 | 1
826 |
827 |
828 |
829 |
830 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
831 | 1
832 |
833 |
834 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
835 | 1
836 |
837 |
838 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
839 | 1
840 |
841 |
842 |
843 |
844 | ..\
845 | 1
846 |
847 |
848 | ..\
849 | 1
850 |
851 |
852 | ..\
853 | 1
854 |
855 |
856 |
857 |
858 | 1
859 |
860 |
861 | 1
862 |
863 |
864 | 1
865 |
866 |
867 |
868 |
869 | ..\$(PROJECTNAME).launchscreen
870 | 64
871 |
872 |
873 | ..\$(PROJECTNAME).launchscreen
874 | 64
875 |
876 |
877 |
878 |
879 | 1
880 |
881 |
882 | 1
883 |
884 |
885 | 1
886 |
887 |
888 |
889 |
890 | Assets
891 | 1
892 |
893 |
894 | Assets
895 | 1
896 |
897 |
898 |
899 |
900 | Assets
901 | 1
902 |
903 |
904 | Assets
905 | 1
906 |
907 |
908 |
909 |
910 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
911 | 1
912 |
913 |
914 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
915 | 1
916 |
917 |
918 |
919 |
920 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
921 | 1
922 |
923 |
924 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
925 | 1
926 |
927 |
928 |
929 |
930 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
931 | 1
932 |
933 |
934 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
935 | 1
936 |
937 |
938 |
939 |
940 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
941 | 1
942 |
943 |
944 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
945 | 1
946 |
947 |
948 |
949 |
950 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
951 | 1
952 |
953 |
954 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
955 | 1
956 |
957 |
958 |
959 |
960 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
961 | 1
962 |
963 |
964 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
965 | 1
966 |
967 |
968 |
969 |
970 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
971 | 1
972 |
973 |
974 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
975 | 1
976 |
977 |
978 |
979 |
980 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
981 | 1
982 |
983 |
984 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
985 | 1
986 |
987 |
988 |
989 |
990 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
991 | 1
992 |
993 |
994 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
995 | 1
996 |
997 |
998 |
999 |
1000 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
1001 | 1
1002 |
1003 |
1004 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
1005 | 1
1006 |
1007 |
1008 |
1009 |
1010 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
1011 | 1
1012 |
1013 |
1014 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
1015 | 1
1016 |
1017 |
1018 |
1019 |
1020 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
1021 | 1
1022 |
1023 |
1024 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
1025 | 1
1026 |
1027 |
1028 |
1029 |
1030 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
1031 | 1
1032 |
1033 |
1034 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
1035 | 1
1036 |
1037 |
1038 |
1039 |
1040 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
1041 | 1
1042 |
1043 |
1044 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
1045 | 1
1046 |
1047 |
1048 |
1049 |
1050 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
1051 | 1
1052 |
1053 |
1054 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
1055 | 1
1056 |
1057 |
1058 |
1059 |
1060 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
1061 | 1
1062 |
1063 |
1064 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
1065 | 1
1066 |
1067 |
1068 |
1069 |
1070 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
1071 | 1
1072 |
1073 |
1074 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
1075 | 1
1076 |
1077 |
1078 |
1079 |
1080 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
1081 | 1
1082 |
1083 |
1084 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
1085 | 1
1086 |
1087 |
1088 |
1089 |
1090 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
1091 | 1
1092 |
1093 |
1094 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
1095 | 1
1096 |
1097 |
1098 |
1099 |
1100 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
1101 | 1
1102 |
1103 |
1104 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
1105 | 1
1106 |
1107 |
1108 |
1109 |
1110 |
1111 |
1112 |
1113 |
1114 |
1115 |
1116 |
1117 |
1118 |
1119 |
1120 |
1121 |
1122 | True
1123 | True
1124 |
1125 |
1126 | 12
1127 |
1128 |
1129 |
1130 |
1131 |
1132 |
--------------------------------------------------------------------------------