@dimer47/capacitor-plugin-printer 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CapacitorPluginPrinter.podspec +17 -0
- package/LICENSE +202 -0
- package/Package.swift +31 -0
- package/README.md +505 -0
- package/android/build.gradle +68 -0
- package/android/src/main/AndroidManifest.xml +3 -0
- package/android/src/main/kotlin/com/nichedev/capacitor/printer/PrintAdapter.kt +73 -0
- package/android/src/main/kotlin/com/nichedev/capacitor/printer/PrintContent.kt +78 -0
- package/android/src/main/kotlin/com/nichedev/capacitor/printer/PrintIO.kt +136 -0
- package/android/src/main/kotlin/com/nichedev/capacitor/printer/PrintManager.kt +219 -0
- package/android/src/main/kotlin/com/nichedev/capacitor/printer/PrintOptions.kt +260 -0
- package/android/src/main/kotlin/com/nichedev/capacitor/printer/PrintProxy.kt +44 -0
- package/android/src/main/kotlin/com/nichedev/capacitor/printer/PrinterPlugin.kt +267 -0
- package/dist/esm/definitions.d.ts +307 -0
- package/dist/esm/definitions.js +2 -0
- package/dist/esm/definitions.js.map +1 -0
- package/dist/esm/index.d.ts +4 -0
- package/dist/esm/index.js +7 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/web.d.ts +13 -0
- package/dist/esm/web.js +47 -0
- package/dist/esm/web.js.map +1 -0
- package/dist/plugin.cjs.js +61 -0
- package/dist/plugin.cjs.js.map +1 -0
- package/dist/plugin.js +64 -0
- package/dist/plugin.js.map +1 -0
- package/ios/Sources/PrinterPlugin/PrinterControllerHelper.swift +33 -0
- package/ios/Sources/PrinterPlugin/PrinterFont.swift +99 -0
- package/ios/Sources/PrinterPlugin/PrinterInfo.swift +64 -0
- package/ios/Sources/PrinterPlugin/PrinterItem.swift +104 -0
- package/ios/Sources/PrinterPlugin/PrinterLayout.swift +61 -0
- package/ios/Sources/PrinterPlugin/PrinterPaper.swift +71 -0
- package/ios/Sources/PrinterPlugin/PrinterPlugin.swift +327 -0
- package/ios/Sources/PrinterPlugin/PrinterRenderer.swift +135 -0
- package/ios/Sources/PrinterPlugin/PrinterUnit.swift +45 -0
- package/package.json +75 -0
package/dist/esm/web.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { WebPlugin } from '@capacitor/core';
|
|
2
|
+
export class PrinterWeb extends WebPlugin {
|
|
3
|
+
async print(options) {
|
|
4
|
+
if (options.content) {
|
|
5
|
+
const printWindow = window.open('', '_blank');
|
|
6
|
+
if (printWindow) {
|
|
7
|
+
printWindow.document.write(options.content);
|
|
8
|
+
printWindow.document.close();
|
|
9
|
+
printWindow.focus();
|
|
10
|
+
printWindow.print();
|
|
11
|
+
printWindow.close();
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
window.print();
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
window.print();
|
|
19
|
+
}
|
|
20
|
+
return { success: true };
|
|
21
|
+
}
|
|
22
|
+
async printHtml({ html, ...opts }) {
|
|
23
|
+
return this.print({ content: html, ...opts });
|
|
24
|
+
}
|
|
25
|
+
async printPdf(_options) {
|
|
26
|
+
throw this.unimplemented('printPdf() is not available on web.');
|
|
27
|
+
}
|
|
28
|
+
async printBase64(_options) {
|
|
29
|
+
throw this.unimplemented('printBase64() is not available on web.');
|
|
30
|
+
}
|
|
31
|
+
async printFile(_options) {
|
|
32
|
+
throw this.unimplemented('printFile() is not available on web.');
|
|
33
|
+
}
|
|
34
|
+
async printWebView(options) {
|
|
35
|
+
return this.print({ ...options });
|
|
36
|
+
}
|
|
37
|
+
async canPrintItem(_options) {
|
|
38
|
+
return { available: typeof window.print === 'function' };
|
|
39
|
+
}
|
|
40
|
+
async getPrintableTypes() {
|
|
41
|
+
return { types: [] };
|
|
42
|
+
}
|
|
43
|
+
async pick(_options) {
|
|
44
|
+
throw this.unimplemented('pick() is not available on web.');
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=web.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAkB5C,MAAM,OAAO,UAAW,SAAQ,SAAS;IACvC,KAAK,CAAC,KAAK,CAAC,OAAqB;QAC/B,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;YACpB,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;YAC9C,IAAI,WAAW,EAAE,CAAC;gBAChB,WAAW,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;gBAC5C,WAAW,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;gBAC7B,WAAW,CAAC,KAAK,EAAE,CAAC;gBACpB,WAAW,CAAC,KAAK,EAAE,CAAC;gBACpB,WAAW,CAAC,KAAK,EAAE,CAAC;YACtB,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,KAAK,EAAE,CAAC;YACjB,CAAC;QACH,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,KAAK,EAAE,CAAC;QACjB,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC3B,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,GAAG,IAAI,EAAoB;QACjD,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC;IAChD,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,QAAyB;QACtC,MAAM,IAAI,CAAC,aAAa,CAAC,qCAAqC,CAAC,CAAC;IAClE,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,QAA4B;QAC5C,MAAM,IAAI,CAAC,aAAa,CAAC,wCAAwC,CAAC,CAAC;IACrE,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,QAA0B;QACxC,MAAM,IAAI,CAAC,aAAa,CAAC,sCAAsC,CAAC,CAAC;IACnE,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,OAA6B;QAC9C,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;IACpC,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,QAA0B;QAC3C,OAAO,EAAE,SAAS,EAAE,OAAO,MAAM,CAAC,KAAK,KAAK,UAAU,EAAE,CAAC;IAC3D,CAAC;IAED,KAAK,CAAC,iBAAiB;QACrB,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;IACvB,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,QAAsB;QAC/B,MAAM,IAAI,CAAC,aAAa,CAAC,iCAAiC,CAAC,CAAC;IAC9D,CAAC;CACF"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var core = require('@capacitor/core');
|
|
4
|
+
|
|
5
|
+
const Printer = core.registerPlugin('Printer', {
|
|
6
|
+
web: () => Promise.resolve().then(function () { return web; }).then((m) => new m.PrinterWeb()),
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
class PrinterWeb extends core.WebPlugin {
|
|
10
|
+
async print(options) {
|
|
11
|
+
if (options.content) {
|
|
12
|
+
const printWindow = window.open('', '_blank');
|
|
13
|
+
if (printWindow) {
|
|
14
|
+
printWindow.document.write(options.content);
|
|
15
|
+
printWindow.document.close();
|
|
16
|
+
printWindow.focus();
|
|
17
|
+
printWindow.print();
|
|
18
|
+
printWindow.close();
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
window.print();
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
window.print();
|
|
26
|
+
}
|
|
27
|
+
return { success: true };
|
|
28
|
+
}
|
|
29
|
+
async printHtml({ html, ...opts }) {
|
|
30
|
+
return this.print({ content: html, ...opts });
|
|
31
|
+
}
|
|
32
|
+
async printPdf(_options) {
|
|
33
|
+
throw this.unimplemented('printPdf() is not available on web.');
|
|
34
|
+
}
|
|
35
|
+
async printBase64(_options) {
|
|
36
|
+
throw this.unimplemented('printBase64() is not available on web.');
|
|
37
|
+
}
|
|
38
|
+
async printFile(_options) {
|
|
39
|
+
throw this.unimplemented('printFile() is not available on web.');
|
|
40
|
+
}
|
|
41
|
+
async printWebView(options) {
|
|
42
|
+
return this.print({ ...options });
|
|
43
|
+
}
|
|
44
|
+
async canPrintItem(_options) {
|
|
45
|
+
return { available: typeof window.print === 'function' };
|
|
46
|
+
}
|
|
47
|
+
async getPrintableTypes() {
|
|
48
|
+
return { types: [] };
|
|
49
|
+
}
|
|
50
|
+
async pick(_options) {
|
|
51
|
+
throw this.unimplemented('pick() is not available on web.');
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
var web = /*#__PURE__*/Object.freeze({
|
|
56
|
+
__proto__: null,
|
|
57
|
+
PrinterWeb: PrinterWeb
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
exports.Printer = Printer;
|
|
61
|
+
//# sourceMappingURL=plugin.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.cjs.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst Printer = registerPlugin('Printer', {\n web: () => import('./web').then((m) => new m.PrinterWeb()),\n});\nexport * from './definitions';\nexport { Printer };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nexport class PrinterWeb extends WebPlugin {\n async print(options) {\n if (options.content) {\n const printWindow = window.open('', '_blank');\n if (printWindow) {\n printWindow.document.write(options.content);\n printWindow.document.close();\n printWindow.focus();\n printWindow.print();\n printWindow.close();\n }\n else {\n window.print();\n }\n }\n else {\n window.print();\n }\n return { success: true };\n }\n async printHtml({ html, ...opts }) {\n return this.print({ content: html, ...opts });\n }\n async printPdf(_options) {\n throw this.unimplemented('printPdf() is not available on web.');\n }\n async printBase64(_options) {\n throw this.unimplemented('printBase64() is not available on web.');\n }\n async printFile(_options) {\n throw this.unimplemented('printFile() is not available on web.');\n }\n async printWebView(options) {\n return this.print({ ...options });\n }\n async canPrintItem(_options) {\n return { available: typeof window.print === 'function' };\n }\n async getPrintableTypes() {\n return { types: [] };\n }\n async pick(_options) {\n throw this.unimplemented('pick() is not available on web.');\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":";;;;AACK,MAAC,OAAO,GAAGA,mBAAc,CAAC,SAAS,EAAE;AAC1C,IAAI,GAAG,EAAE,MAAM,mDAAe,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,UAAU,EAAE,CAAC;AAC9D,CAAC;;ACFM,MAAM,UAAU,SAASC,cAAS,CAAC;AAC1C,IAAI,MAAM,KAAK,CAAC,OAAO,EAAE;AACzB,QAAQ,IAAI,OAAO,CAAC,OAAO,EAAE;AAC7B,YAAY,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,QAAQ,CAAC;AACzD,YAAY,IAAI,WAAW,EAAE;AAC7B,gBAAgB,WAAW,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;AAC3D,gBAAgB,WAAW,CAAC,QAAQ,CAAC,KAAK,EAAE;AAC5C,gBAAgB,WAAW,CAAC,KAAK,EAAE;AACnC,gBAAgB,WAAW,CAAC,KAAK,EAAE;AACnC,gBAAgB,WAAW,CAAC,KAAK,EAAE;AACnC,YAAY;AACZ,iBAAiB;AACjB,gBAAgB,MAAM,CAAC,KAAK,EAAE;AAC9B,YAAY;AACZ,QAAQ;AACR,aAAa;AACb,YAAY,MAAM,CAAC,KAAK,EAAE;AAC1B,QAAQ;AACR,QAAQ,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE;AAChC,IAAI;AACJ,IAAI,MAAM,SAAS,CAAC,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,EAAE;AACvC,QAAQ,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,CAAC;AACrD,IAAI;AACJ,IAAI,MAAM,QAAQ,CAAC,QAAQ,EAAE;AAC7B,QAAQ,MAAM,IAAI,CAAC,aAAa,CAAC,qCAAqC,CAAC;AACvE,IAAI;AACJ,IAAI,MAAM,WAAW,CAAC,QAAQ,EAAE;AAChC,QAAQ,MAAM,IAAI,CAAC,aAAa,CAAC,wCAAwC,CAAC;AAC1E,IAAI;AACJ,IAAI,MAAM,SAAS,CAAC,QAAQ,EAAE;AAC9B,QAAQ,MAAM,IAAI,CAAC,aAAa,CAAC,sCAAsC,CAAC;AACxE,IAAI;AACJ,IAAI,MAAM,YAAY,CAAC,OAAO,EAAE;AAChC,QAAQ,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,OAAO,EAAE,CAAC;AACzC,IAAI;AACJ,IAAI,MAAM,YAAY,CAAC,QAAQ,EAAE;AACjC,QAAQ,OAAO,EAAE,SAAS,EAAE,OAAO,MAAM,CAAC,KAAK,KAAK,UAAU,EAAE;AAChE,IAAI;AACJ,IAAI,MAAM,iBAAiB,GAAG;AAC9B,QAAQ,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE;AAC5B,IAAI;AACJ,IAAI,MAAM,IAAI,CAAC,QAAQ,EAAE;AACzB,QAAQ,MAAM,IAAI,CAAC,aAAa,CAAC,iCAAiC,CAAC;AACnE,IAAI;AACJ;;;;;;;;;"}
|
package/dist/plugin.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
var capacitorPrinter = (function (exports, core) {
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const Printer = core.registerPlugin('Printer', {
|
|
5
|
+
web: () => Promise.resolve().then(function () { return web; }).then((m) => new m.PrinterWeb()),
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
class PrinterWeb extends core.WebPlugin {
|
|
9
|
+
async print(options) {
|
|
10
|
+
if (options.content) {
|
|
11
|
+
const printWindow = window.open('', '_blank');
|
|
12
|
+
if (printWindow) {
|
|
13
|
+
printWindow.document.write(options.content);
|
|
14
|
+
printWindow.document.close();
|
|
15
|
+
printWindow.focus();
|
|
16
|
+
printWindow.print();
|
|
17
|
+
printWindow.close();
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
window.print();
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
window.print();
|
|
25
|
+
}
|
|
26
|
+
return { success: true };
|
|
27
|
+
}
|
|
28
|
+
async printHtml({ html, ...opts }) {
|
|
29
|
+
return this.print({ content: html, ...opts });
|
|
30
|
+
}
|
|
31
|
+
async printPdf(_options) {
|
|
32
|
+
throw this.unimplemented('printPdf() is not available on web.');
|
|
33
|
+
}
|
|
34
|
+
async printBase64(_options) {
|
|
35
|
+
throw this.unimplemented('printBase64() is not available on web.');
|
|
36
|
+
}
|
|
37
|
+
async printFile(_options) {
|
|
38
|
+
throw this.unimplemented('printFile() is not available on web.');
|
|
39
|
+
}
|
|
40
|
+
async printWebView(options) {
|
|
41
|
+
return this.print({ ...options });
|
|
42
|
+
}
|
|
43
|
+
async canPrintItem(_options) {
|
|
44
|
+
return { available: typeof window.print === 'function' };
|
|
45
|
+
}
|
|
46
|
+
async getPrintableTypes() {
|
|
47
|
+
return { types: [] };
|
|
48
|
+
}
|
|
49
|
+
async pick(_options) {
|
|
50
|
+
throw this.unimplemented('pick() is not available on web.');
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
var web = /*#__PURE__*/Object.freeze({
|
|
55
|
+
__proto__: null,
|
|
56
|
+
PrinterWeb: PrinterWeb
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
exports.Printer = Printer;
|
|
60
|
+
|
|
61
|
+
return exports;
|
|
62
|
+
|
|
63
|
+
})({}, capacitorExports);
|
|
64
|
+
//# sourceMappingURL=plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst Printer = registerPlugin('Printer', {\n web: () => import('./web').then((m) => new m.PrinterWeb()),\n});\nexport * from './definitions';\nexport { Printer };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nexport class PrinterWeb extends WebPlugin {\n async print(options) {\n if (options.content) {\n const printWindow = window.open('', '_blank');\n if (printWindow) {\n printWindow.document.write(options.content);\n printWindow.document.close();\n printWindow.focus();\n printWindow.print();\n printWindow.close();\n }\n else {\n window.print();\n }\n }\n else {\n window.print();\n }\n return { success: true };\n }\n async printHtml({ html, ...opts }) {\n return this.print({ content: html, ...opts });\n }\n async printPdf(_options) {\n throw this.unimplemented('printPdf() is not available on web.');\n }\n async printBase64(_options) {\n throw this.unimplemented('printBase64() is not available on web.');\n }\n async printFile(_options) {\n throw this.unimplemented('printFile() is not available on web.');\n }\n async printWebView(options) {\n return this.print({ ...options });\n }\n async canPrintItem(_options) {\n return { available: typeof window.print === 'function' };\n }\n async getPrintableTypes() {\n return { types: [] };\n }\n async pick(_options) {\n throw this.unimplemented('pick() is not available on web.');\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":";;;AACK,UAAC,OAAO,GAAGA,mBAAc,CAAC,SAAS,EAAE;IAC1C,IAAI,GAAG,EAAE,MAAM,mDAAe,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,UAAU,EAAE,CAAC;IAC9D,CAAC;;ICFM,MAAM,UAAU,SAASC,cAAS,CAAC;IAC1C,IAAI,MAAM,KAAK,CAAC,OAAO,EAAE;IACzB,QAAQ,IAAI,OAAO,CAAC,OAAO,EAAE;IAC7B,YAAY,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,QAAQ,CAAC;IACzD,YAAY,IAAI,WAAW,EAAE;IAC7B,gBAAgB,WAAW,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;IAC3D,gBAAgB,WAAW,CAAC,QAAQ,CAAC,KAAK,EAAE;IAC5C,gBAAgB,WAAW,CAAC,KAAK,EAAE;IACnC,gBAAgB,WAAW,CAAC,KAAK,EAAE;IACnC,gBAAgB,WAAW,CAAC,KAAK,EAAE;IACnC,YAAY;IACZ,iBAAiB;IACjB,gBAAgB,MAAM,CAAC,KAAK,EAAE;IAC9B,YAAY;IACZ,QAAQ;IACR,aAAa;IACb,YAAY,MAAM,CAAC,KAAK,EAAE;IAC1B,QAAQ;IACR,QAAQ,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE;IAChC,IAAI;IACJ,IAAI,MAAM,SAAS,CAAC,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,EAAE;IACvC,QAAQ,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,CAAC;IACrD,IAAI;IACJ,IAAI,MAAM,QAAQ,CAAC,QAAQ,EAAE;IAC7B,QAAQ,MAAM,IAAI,CAAC,aAAa,CAAC,qCAAqC,CAAC;IACvE,IAAI;IACJ,IAAI,MAAM,WAAW,CAAC,QAAQ,EAAE;IAChC,QAAQ,MAAM,IAAI,CAAC,aAAa,CAAC,wCAAwC,CAAC;IAC1E,IAAI;IACJ,IAAI,MAAM,SAAS,CAAC,QAAQ,EAAE;IAC9B,QAAQ,MAAM,IAAI,CAAC,aAAa,CAAC,sCAAsC,CAAC;IACxE,IAAI;IACJ,IAAI,MAAM,YAAY,CAAC,OAAO,EAAE;IAChC,QAAQ,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,OAAO,EAAE,CAAC;IACzC,IAAI;IACJ,IAAI,MAAM,YAAY,CAAC,QAAQ,EAAE;IACjC,QAAQ,OAAO,EAAE,SAAS,EAAE,OAAO,MAAM,CAAC,KAAK,KAAK,UAAU,EAAE;IAChE,IAAI;IACJ,IAAI,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE;IAC5B,IAAI;IACJ,IAAI,MAAM,IAAI,CAAC,QAAQ,EAAE;IACzB,QAAQ,MAAM,IAAI,CAAC,aAAa,CAAC,iCAAiC,CAAC;IACnE,IAAI;IACJ;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import UIKit
|
|
3
|
+
|
|
4
|
+
/// Configures the shared UIPrintInteractionController with given settings.
|
|
5
|
+
class PrinterControllerHelper {
|
|
6
|
+
|
|
7
|
+
static func sharedController(with settings: [String: Any]) -> UIPrintInteractionController {
|
|
8
|
+
let ctrl = UIPrintInteractionController.shared
|
|
9
|
+
|
|
10
|
+
// Reset previous state to avoid stale data from prior print jobs
|
|
11
|
+
ctrl.printPageRenderer = nil
|
|
12
|
+
ctrl.printFormatter = nil
|
|
13
|
+
ctrl.printingItem = nil
|
|
14
|
+
ctrl.printingItems = nil
|
|
15
|
+
|
|
16
|
+
ctrl.printInfo = PrinterInfo.printInfo(with: settings)
|
|
17
|
+
|
|
18
|
+
// Default to showing paper selection so users can pick A4, A5, Letter, etc.
|
|
19
|
+
ctrl.showsPaperSelectionForLoadedPapers = true
|
|
20
|
+
ctrl.showsNumberOfCopies = true
|
|
21
|
+
|
|
22
|
+
if let ui = settings["ui"] as? [String: Any] {
|
|
23
|
+
if let hide = ui["hideNumberOfCopies"] as? Bool, hide {
|
|
24
|
+
ctrl.showsNumberOfCopies = false
|
|
25
|
+
}
|
|
26
|
+
if let hide = ui["hidePaperFormat"] as? Bool, hide {
|
|
27
|
+
ctrl.showsPaperSelectionForLoadedPapers = false
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return ctrl
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import UIKit
|
|
3
|
+
|
|
4
|
+
/// Handles font styling and attributes from settings dictionary.
|
|
5
|
+
class PrinterFont {
|
|
6
|
+
|
|
7
|
+
private let settings: [String: Any]
|
|
8
|
+
|
|
9
|
+
init(dictionary: [String: Any]?) {
|
|
10
|
+
self.settings = dictionary ?? [:]
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
var attributes: [NSAttributedString.Key: Any] {
|
|
14
|
+
let style = NSMutableParagraphStyle()
|
|
15
|
+
style.alignment = self.alignment
|
|
16
|
+
|
|
17
|
+
return [
|
|
18
|
+
.font: self.font,
|
|
19
|
+
.paragraphStyle: style,
|
|
20
|
+
.foregroundColor: self.color,
|
|
21
|
+
]
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
var font: UIFont {
|
|
25
|
+
var size = (settings["size"] as? NSNumber)?.doubleValue ?? 0
|
|
26
|
+
|
|
27
|
+
if size <= 0 {
|
|
28
|
+
size = Double(UIFont.smallSystemFontSize)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
var uiFont: UIFont
|
|
32
|
+
if let fontName = settings["name"] as? String,
|
|
33
|
+
let namedFont = UIFont(name: fontName, size: size)
|
|
34
|
+
{
|
|
35
|
+
uiFont = namedFont
|
|
36
|
+
} else {
|
|
37
|
+
uiFont = UIFont.systemFont(ofSize: size)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
var traits: UIFontDescriptor.SymbolicTraits = []
|
|
41
|
+
|
|
42
|
+
if settings["bold"] as? Bool == true {
|
|
43
|
+
traits.insert(.traitBold)
|
|
44
|
+
}
|
|
45
|
+
if settings["italic"] as? Bool == true {
|
|
46
|
+
traits.insert(.traitItalic)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if !traits.isEmpty,
|
|
50
|
+
let descriptor = uiFont.fontDescriptor.withSymbolicTraits(traits)
|
|
51
|
+
{
|
|
52
|
+
uiFont = UIFont(descriptor: descriptor, size: size)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return uiFont
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
var color: UIColor {
|
|
59
|
+
guard let hex = settings["color"] as? String, !hex.isEmpty else {
|
|
60
|
+
return .darkText
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return PrinterFont.color(fromHex: hex) ?? .darkText
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
var alignment: NSTextAlignment {
|
|
67
|
+
guard let align = settings["align"] as? String else {
|
|
68
|
+
return .natural
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
switch align {
|
|
72
|
+
case "left": return .left
|
|
73
|
+
case "right": return .right
|
|
74
|
+
case "center": return .center
|
|
75
|
+
case "justified": return .justified
|
|
76
|
+
default: return .natural
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// MARK: - Private
|
|
81
|
+
|
|
82
|
+
private static func color(fromHex hex: String) -> UIColor? {
|
|
83
|
+
var cleanHex = hex
|
|
84
|
+
if cleanHex.hasPrefix("#") {
|
|
85
|
+
cleanHex = String(cleanHex.dropFirst())
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
var rgb: UInt64 = 0
|
|
89
|
+
let scanner = Scanner(string: cleanHex)
|
|
90
|
+
scanner.scanHexInt64(&rgb)
|
|
91
|
+
|
|
92
|
+
return UIColor(
|
|
93
|
+
red: CGFloat((rgb & 0xFF0000) >> 16) / 255.0,
|
|
94
|
+
green: CGFloat((rgb & 0xFF00) >> 8) / 255.0,
|
|
95
|
+
blue: CGFloat(rgb & 0xFF) / 255.0,
|
|
96
|
+
alpha: 1.0
|
|
97
|
+
)
|
|
98
|
+
}
|
|
99
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import UIKit
|
|
3
|
+
|
|
4
|
+
/// Converts settings dictionary to UIPrintInfo.
|
|
5
|
+
class PrinterInfo {
|
|
6
|
+
|
|
7
|
+
static func printInfo(with spec: [String: Any]) -> UIPrintInfo {
|
|
8
|
+
let info = UIPrintInfo(dictionary: nil)
|
|
9
|
+
let duplex = spec["duplex"] as? String
|
|
10
|
+
let jobName = spec["name"] as? String
|
|
11
|
+
let copies = max((spec["copies"] as? Int) ?? 1, 1)
|
|
12
|
+
|
|
13
|
+
// Orientation
|
|
14
|
+
if let orientation = spec["orientation"] as? String {
|
|
15
|
+
switch orientation {
|
|
16
|
+
case "landscape":
|
|
17
|
+
info.orientation = .landscape
|
|
18
|
+
case "portrait":
|
|
19
|
+
info.orientation = .portrait
|
|
20
|
+
default:
|
|
21
|
+
break
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Output type
|
|
26
|
+
let monochrome = spec["monochrome"] as? Bool ?? false
|
|
27
|
+
let photo = spec["photo"] as? Bool ?? false
|
|
28
|
+
|
|
29
|
+
if monochrome {
|
|
30
|
+
info.outputType = photo ? .photoGrayscale : .grayscale
|
|
31
|
+
} else if photo {
|
|
32
|
+
info.outputType = .photo
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Duplex
|
|
36
|
+
if let duplex = duplex {
|
|
37
|
+
switch duplex {
|
|
38
|
+
case "long":
|
|
39
|
+
info.duplex = .longEdge
|
|
40
|
+
case "short":
|
|
41
|
+
info.duplex = .shortEdge
|
|
42
|
+
case "none":
|
|
43
|
+
info.duplex = .none
|
|
44
|
+
default:
|
|
45
|
+
break
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Copies (using private API via KVC, same as original plugin)
|
|
50
|
+
if copies > 1 {
|
|
51
|
+
let selector = NSSelectorFromString("_copies")
|
|
52
|
+
if info.responds(to: selector) {
|
|
53
|
+
info.setValue(NSNumber(value: copies), forKey: "_copies")
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Job name
|
|
58
|
+
if let jobName = jobName, !jobName.isEmpty {
|
|
59
|
+
info.jobName = jobName
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return info
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import UIKit
|
|
3
|
+
|
|
4
|
+
/// Handles converting URLs/paths into printable items (NSURL or NSData).
|
|
5
|
+
class PrinterItem {
|
|
6
|
+
|
|
7
|
+
/// Returns the printing item referred by URL, either as URL or Data.
|
|
8
|
+
static func item(from urlString: String) -> Any? {
|
|
9
|
+
return PrinterItem().itemFromURL(urlString)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/// Returns whether the print framework can render the referenced file.
|
|
13
|
+
static func canPrintURL(_ url: String?) -> Bool {
|
|
14
|
+
guard let url = url, !(url as NSString).isEqual(to: NSNull().description), !url.isEmpty else {
|
|
15
|
+
return UIPrintInteractionController.isPrintingAvailable
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
guard URL(string: url)?.scheme != nil else {
|
|
19
|
+
return UIPrintInteractionController.isPrintingAvailable
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
let item = PrinterItem().itemFromURL(url)
|
|
23
|
+
|
|
24
|
+
if let data = item as? Data {
|
|
25
|
+
return UIPrintInteractionController.canPrint(data)
|
|
26
|
+
} else if let fileURL = item as? URL {
|
|
27
|
+
return UIPrintInteractionController.canPrint(fileURL)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return false
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// MARK: - Private
|
|
34
|
+
|
|
35
|
+
private func itemFromURL(_ path: String) -> Any? {
|
|
36
|
+
if path.hasPrefix("file:///") {
|
|
37
|
+
return urlForFile(path)
|
|
38
|
+
} else if path.hasPrefix("res:") {
|
|
39
|
+
return urlForResource(path)
|
|
40
|
+
} else if path.hasPrefix("file://") {
|
|
41
|
+
return urlForAsset(path)
|
|
42
|
+
} else if path.hasPrefix("base64:") {
|
|
43
|
+
return dataFromBase64(path)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
let fm = FileManager.default
|
|
47
|
+
if !fm.fileExists(atPath: path) {
|
|
48
|
+
NSLog("[capacitor-plugin-printer] File not found: %@", path)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return URL(fileURLWithPath: path)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
private func urlForFile(_ path: String) -> URL {
|
|
55
|
+
let absPath = String(path.dropFirst(7))
|
|
56
|
+
let fm = FileManager.default
|
|
57
|
+
|
|
58
|
+
if !fm.fileExists(atPath: absPath) {
|
|
59
|
+
NSLog("[capacitor-plugin-printer] File not found: %@", absPath)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return URL(fileURLWithPath: absPath)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
private func urlForResource(_ path: String) -> URL {
|
|
66
|
+
let fm = FileManager.default
|
|
67
|
+
let bundlePath = Bundle.main.resourcePath ?? ""
|
|
68
|
+
var adjustedPath = path
|
|
69
|
+
|
|
70
|
+
if path == "res://icon" {
|
|
71
|
+
if UIDevice.current.userInterfaceIdiom == .pad {
|
|
72
|
+
adjustedPath = "res://AppIcon76x76@2x~ipad.png"
|
|
73
|
+
} else {
|
|
74
|
+
adjustedPath = "res://AppIcon60x60@2x.png"
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
let absPath = bundlePath + adjustedPath.replacingOccurrences(of: "res:/", with: "")
|
|
79
|
+
|
|
80
|
+
if !fm.fileExists(atPath: absPath) {
|
|
81
|
+
NSLog("[capacitor-plugin-printer] File not found: %@", absPath)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return URL(fileURLWithPath: absPath)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
private func urlForAsset(_ path: String) -> URL {
|
|
88
|
+
let fm = FileManager.default
|
|
89
|
+
let bundlePath = Bundle.main.bundlePath
|
|
90
|
+
let absPath = bundlePath + "/public" + String(path.dropFirst(6))
|
|
91
|
+
|
|
92
|
+
if !fm.fileExists(atPath: absPath) {
|
|
93
|
+
NSLog("[capacitor-plugin-printer] File not found: %@", absPath)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return URL(fileURLWithPath: absPath)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
private func dataFromBase64(_ url: String) -> Data? {
|
|
100
|
+
guard url.count > 9 else { return nil }
|
|
101
|
+
let base64String = String(url.dropFirst(9))
|
|
102
|
+
return Data(base64Encoded: base64String, options: .ignoreUnknownCharacters)
|
|
103
|
+
}
|
|
104
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import UIKit
|
|
3
|
+
|
|
4
|
+
/// Configures print formatter layout (margins, max dimensions, font).
|
|
5
|
+
class PrinterLayout {
|
|
6
|
+
|
|
7
|
+
private var contentInsets: UIEdgeInsets = .zero
|
|
8
|
+
private var maximumContentWidth: CGFloat = 0
|
|
9
|
+
private var maximumContentHeight: CGFloat = 0
|
|
10
|
+
|
|
11
|
+
init(dictionary spec: [String: Any]?) {
|
|
12
|
+
guard let spec = spec else { return }
|
|
13
|
+
|
|
14
|
+
if let margin = spec["margin"] as? [String: Any] {
|
|
15
|
+
contentInsets = UIEdgeInsets(
|
|
16
|
+
top: CGFloat(PrinterUnit.convert(margin["top"])),
|
|
17
|
+
left: CGFloat(PrinterUnit.convert(margin["left"])),
|
|
18
|
+
bottom: CGFloat(PrinterUnit.convert(margin["bottom"])),
|
|
19
|
+
right: CGFloat(PrinterUnit.convert(margin["right"]))
|
|
20
|
+
)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
maximumContentWidth = CGFloat(PrinterUnit.convert(spec["maxWidth"]))
|
|
24
|
+
maximumContentHeight = CGFloat(PrinterUnit.convert(spec["maxHeight"]))
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/// Configures formatter with layout and optional font settings.
|
|
28
|
+
static func configureFormatter(
|
|
29
|
+
_ formatter: UIPrintFormatter, withSettings settings: [String: Any]
|
|
30
|
+
) -> UIPrintFormatter {
|
|
31
|
+
let layout = PrinterLayout(dictionary: settings)
|
|
32
|
+
layout.configureFormatter(formatter)
|
|
33
|
+
|
|
34
|
+
if let textFormatter = formatter as? UISimpleTextPrintFormatter {
|
|
35
|
+
layout.configureTextFormatter(textFormatter, withSettings: settings)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return formatter
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
func configureFormatter(_ formatter: UIPrintFormatter) {
|
|
42
|
+
if maximumContentHeight > 0 {
|
|
43
|
+
formatter.maximumContentHeight = maximumContentHeight
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if maximumContentWidth > 0 {
|
|
47
|
+
formatter.maximumContentWidth = maximumContentWidth
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
formatter.perPageContentInsets = contentInsets
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
func configureTextFormatter(
|
|
54
|
+
_ formatter: UISimpleTextPrintFormatter, withSettings settings: [String: Any]
|
|
55
|
+
) {
|
|
56
|
+
let font = PrinterFont(dictionary: settings["font"] as? [String: Any])
|
|
57
|
+
formatter.font = font.font
|
|
58
|
+
formatter.color = font.color
|
|
59
|
+
formatter.textAlignment = font.alignment
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import UIKit
|
|
3
|
+
|
|
4
|
+
/// Handles paper size selection for print jobs.
|
|
5
|
+
/// Supports both named sizes (A4, A5, Letter, etc.) and custom width/height.
|
|
6
|
+
class PrinterPaper {
|
|
7
|
+
|
|
8
|
+
let size: CGSize
|
|
9
|
+
let length: CGFloat
|
|
10
|
+
|
|
11
|
+
/// Common paper sizes in points (72 points = 1 inch).
|
|
12
|
+
private static let namedSizes: [String: CGSize] = [
|
|
13
|
+
// ISO A series
|
|
14
|
+
"A0": CGSize(width: 2383.94, height: 3370.39),
|
|
15
|
+
"A1": CGSize(width: 1683.78, height: 2383.94),
|
|
16
|
+
"A2": CGSize(width: 1190.55, height: 1683.78),
|
|
17
|
+
"A3": CGSize(width: 841.89, height: 1190.55),
|
|
18
|
+
"A4": CGSize(width: 595.28, height: 841.89),
|
|
19
|
+
"A5": CGSize(width: 419.53, height: 595.28),
|
|
20
|
+
"A6": CGSize(width: 297.64, height: 419.53),
|
|
21
|
+
"A7": CGSize(width: 209.76, height: 297.64),
|
|
22
|
+
"A8": CGSize(width: 147.40, height: 209.76),
|
|
23
|
+
"A9": CGSize(width: 104.88, height: 147.40),
|
|
24
|
+
"A10": CGSize(width: 73.70, height: 104.88),
|
|
25
|
+
// ISO B series
|
|
26
|
+
"B0": CGSize(width: 2834.65, height: 4008.19),
|
|
27
|
+
"B1": CGSize(width: 2004.09, height: 2834.65),
|
|
28
|
+
"B2": CGSize(width: 1417.32, height: 2004.09),
|
|
29
|
+
"B3": CGSize(width: 1000.63, height: 1417.32),
|
|
30
|
+
"B4": CGSize(width: 708.66, height: 1000.63),
|
|
31
|
+
"B5": CGSize(width: 498.90, height: 708.66),
|
|
32
|
+
"B6": CGSize(width: 354.33, height: 498.90),
|
|
33
|
+
// North America
|
|
34
|
+
"LETTER": CGSize(width: 612, height: 792),
|
|
35
|
+
"LEGAL": CGSize(width: 612, height: 1008),
|
|
36
|
+
"TABLOID": CGSize(width: 792, height: 1224),
|
|
37
|
+
"LEDGER": CGSize(width: 1224, height: 792),
|
|
38
|
+
"JUNIOR_LEGAL": CGSize(width: 576, height: 360),
|
|
39
|
+
"GOVT_LETTER": CGSize(width: 576, height: 756),
|
|
40
|
+
// Photo sizes
|
|
41
|
+
"4X6": CGSize(width: 288, height: 432),
|
|
42
|
+
"5X7": CGSize(width: 360, height: 504),
|
|
43
|
+
"8X10": CGSize(width: 576, height: 720),
|
|
44
|
+
// JIS
|
|
45
|
+
"JIS_B4": CGSize(width: 728.50, height: 1031.81),
|
|
46
|
+
"JIS_B5": CGSize(width: 515.91, height: 728.50),
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
init(dictionary spec: [String: Any]?) {
|
|
50
|
+
let spec = spec ?? [:]
|
|
51
|
+
let name = (spec["name"] as? String)?.uppercased() ?? ""
|
|
52
|
+
|
|
53
|
+
if !name.isEmpty, let namedSize = PrinterPaper.namedSizes[name] {
|
|
54
|
+
self.size = namedSize
|
|
55
|
+
} else {
|
|
56
|
+
self.size = CGSize(
|
|
57
|
+
width: CGFloat(PrinterUnit.convert(spec["width"])),
|
|
58
|
+
height: CGFloat(PrinterUnit.convert(spec["height"]))
|
|
59
|
+
)
|
|
60
|
+
}
|
|
61
|
+
self.length = CGFloat(PrinterUnit.convert(spec["length"]))
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/// Finds the best matching paper from available paper list.
|
|
65
|
+
func bestPaper(from list: [UIPrintPaper]) -> UIPrintPaper? {
|
|
66
|
+
if size.height > 0 || size.width > 0 {
|
|
67
|
+
return UIPrintPaper.bestPaper(forPageSize: size, withPapersFrom: list)
|
|
68
|
+
}
|
|
69
|
+
return nil
|
|
70
|
+
}
|
|
71
|
+
}
|