Update plugin interface with some breaking changes

This commit is contained in:
Sebastián Katzer 2019-01-25 12:42:22 +01:00
parent 98b5d32527
commit ce27a883ab
7 changed files with 321 additions and 169 deletions

View File

@ -23,11 +23,12 @@
@interface APPPrinter : CDVPlugin <UIPrintInteractionControllerDelegate> @interface APPPrinter : CDVPlugin <UIPrintInteractionControllerDelegate>
// Find out whether printing is supported on this platform
- (void) check:(CDVInvokedUrlCommand *)command; - (void) check:(CDVInvokedUrlCommand *)command;
// Displays system interface for selecting a printer
- (void) utis:(CDVInvokedUrlCommand *)command;
- (void) pick:(CDVInvokedUrlCommand *)command; - (void) pick:(CDVInvokedUrlCommand *)command;
// Prints the content
- (void) print:(CDVInvokedUrlCommand *)command; - (void) print:(CDVInvokedUrlCommand *)command;
@end @end

View File

@ -42,22 +42,30 @@
- (void) check:(CDVInvokedUrlCommand *)command - (void) check:(CDVInvokedUrlCommand *)command
{ {
[self.commandDelegate runInBackground:^{ [self.commandDelegate runInBackground:^{
BOOL res = NO; BOOL res = [APPPrinterItem canPrintURL:command.arguments[0]];
if (command.arguments.count == 0)
{
res = UIPrintInteractionController.isPrintingAvailable;
}
else
{
res = [APPPrinterItem canPrintURL:command.arguments[0]];
}
[self sendResultWithMessageAsBool:res [self sendResultWithMessageAsBool:res
callbackId:command.callbackId]; callbackId:command.callbackId];
}]; }];
} }
/*
* List all printable document types (utis).
*/
- (void) utis:(CDVInvokedUrlCommand *)command
{
[self.commandDelegate runInBackground:^{
NSSet *utis = UIPrintInteractionController.printableUTIs;
CDVPluginResult* result =
[CDVPluginResult resultWithStatus:CDVCommandStatus_OK
messageAsArray:utis.allObjects];
[self.commandDelegate sendPluginResult:result
callbackId:command.callbackId];
}];
}
/** /**
* Displays system interface for selecting a printer. * Displays system interface for selecting a printer.
*/ */

View File

@ -23,6 +23,6 @@
+ (id) ItemFromURL:(NSString *)url; + (id) ItemFromURL:(NSString *)url;
+ (BOOL) canPrintURL:(NSString *)url; + (BOOL) canPrintURL:(nullable NSString *)url;
@end @end

View File

@ -45,9 +45,12 @@
* *
* @return true if its able to render the content of the file. * @return true if its able to render the content of the file.
*/ */
+ (BOOL) canPrintURL:(NSString *)url + (BOOL) canPrintURL:(nullable NSString *)url
{ {
if (![NSURL URLWithString:url]) return YES; if (![NSURL URLWithString:url])
{
return UIPrintInteractionController.isPrintingAvailable;
}
id item = [self ItemFromURL:url]; id item = [self ItemFromURL:url];

View File

@ -21,6 +21,6 @@
@interface APPPrinterUnit : NSObject @interface APPPrinterUnit : NSObject
+ (double) convert:(NSString *)unit; + (double) convert:(nullable NSString *)unit;
@end @end

View File

@ -23,8 +23,11 @@
@implementation APPPrinterUnit @implementation APPPrinterUnit
+ (double) convert:(NSString *)unit + (double) convert:(nullable NSString *)unit
{ {
if ([unit isEqual:[NSNull null]])
return 1.0;
if ([unit isEqualToString:@"in"]) if ([unit isEqualToString:@"in"])
return 72.0; return 72.0;

View File

@ -1,6 +1,4 @@
/* /*
Copyright 2013-2016 appPlant GmbH
Licensed to the Apache Software Foundation (ASF) under one Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file or more contributor license agreements. See the NOTICE file
distributed with this work for additional information distributed with this work for additional information
@ -17,23 +15,18 @@
KIND, either express or implied. See the License for the KIND, either express or implied. See the License for the
specific language governing permissions and limitations specific language governing permissions and limitations
under the License. under the License.
*/ */
var exec = require('cordova/exec'); var exec = require('cordova/exec');
/** // Defaults
* List of all available options with their default value. exports._defaults = {
*
* @return {Object}
*/
exports.getDefaults = function () {
return {
// name: 'unknown', // name: 'unknown',
// duplex: 'none', // duplex: 'none',
// landscape: false, // landscape: false,
// graystyle: false, // graystyle: false,
// border: true, // border: true,
copies: 1, // copies: 1,
ui: { ui: {
hideNumberOfCopies: false, hideNumberOfCopies: false,
@ -41,150 +34,188 @@ exports.getDefaults = function () {
bounds: [40, 30, 0, 0] bounds: [40, 30, 0, 0]
}, },
paper: { // paper: {
unit: 'cm', // unit: 'cm',
height: 0, // height: 0,
width: 0, // width: 0,
length: 0 // length: 0
}, // },
layout: { // layout: {
unit: 'cm', // unit: 'cm',
maxHeight: 0, // maxHeight: 0,
maxWidth: 0, // maxWidth: 0,
padding: { top: 0, left: 0, right: 0, bottom: 0 } // padding: { top: 0, left: 0, right: 0, bottom: 0 }
}, // },
header: { // header: {
unit: 'cm', // unit: 'cm',
height: 1, // height: 1,
labels: [{ // labels: [{
text: 'Awesome Printer Plug-in', // text: 'Awesome Printer Plug-in',
style: { // style: {
align: 'center', // align: 'center',
italic: true, // italic: true,
color: '#FF0000' // color: '#FF0000'
} // }
},{ // },{
showPageIndex: true, // showPageIndex: true,
style: { // style: {
align: 'right', // align: 'right',
bold: true // bold: true
} // }
}] // }]
}, // },
footer: { // footer: {
unit: 'mm', // unit: 'mm',
height: 3, // height: 3,
label: { // label: {
text: 'Copyright (c) 2013-2019 Sebastián Katzer', // text: 'Copyright (c) 2013-2019 Sebastián Katzer',
style: { size: 9 }, // style: { size: 9 },
position: { // position: {
unit: 'mm', // unit: 'mm',
top: 1.5, // top: 1.5,
right: 5 // right: 5
} // }
} // }
} // }
};
}; };
/** /**
* Checks if the printer service is avaible (iOS) * Test if the printer service is able to print
* or if services are available (Android). * the ressource specified by URL.
* *
* @param {Function} callback * @param [ String ] uri A file URI.
* A callback function * @param [ Function ] callback The callback function.
* @param {Object?} scope * @param [ Object ] scope The scope for the function.
* The scope of the callback (default: window)
* *
* @return {Boolean} * @return [ Void ]
*/ */
exports.check = function (callback, scope) { exports.canPrint = function (uri, callback, scope) {
var fn = this._createCallbackFn(callback);
exec(fn, null, 'Printer', 'check', []); if (typeof uri == 'function') {
scope = callback;
callback = uri;
uri = null;
}
var fn = this._createCallbackFn(callback, scope);
exec(fn, null, 'Printer', 'check', [uri]);
}; };
/** /**
* @deprecated API call. Use `check` instead! * Returns a list of all printable document types.
*
* @param [ Function ] callback The callback function.
* @param [ Object ] scope The scope for the function.
*
* @return [ Void ]
*/ */
exports.isAvailable = function () { exports.getPrintableUTIs = function (callback, scope) {
exports.check.apply(exports, arguments); var fn = this._createCallbackFn(callback, scope);
exec(fn, null, 'Printer', 'utis', []);
}; };
/** /**
* Displays system interface for selecting a printer. * Displays system interface for selecting a printer.
* *
* @param {Function} callback * @param [ Object ] options Optional options.
* A callback function * @param [ Function ] callback The callback function.
* @param {Object} options * @param [ Object ] scope The scope for the function.
* Options for the printer picker *
* @return [ Void ]
*/ */
exports.pick = function (callback, options) { exports.pick = function (options, callback, scope) {
var fn = this._createCallbackFn(callback);
var params = options || {};
params = this.mergeWithDefaults(params); if (typeof options == 'function') {
scope = callback;
callback = options;
options = {};
}
var fn = this._createCallbackFn(callback, scope),
params = this._mergeWithDefaults(options || {});
exec(fn, null, 'Printer', 'pick', [params]); exec(fn, null, 'Printer', 'pick', [params]);
}; };
/** /**
* Sends the content to the Printing Framework. * Sends the content to the printer.
* *
* @param {String} content * @param [ String ] content The plain/html text or a file URI.
* HTML string or DOM node * @param [ Object ] options Options for the print job.
* if latter, innerHTML is used to get the content * @param [ Function ] callback The callback function.
* @param {Object} options * @param [ Object ] scope The scope for the function.
* Options for the print job
* @param {Function?} callback
* A callback function
* @param {Object?} scope
* The scope of the callback (default: window)
*/ */
exports.print = function (content, options, callback, scope) { exports.print = function (content, options, callback, scope) {
var page = content.innerHTML || content,
params = options || {},
fn = this._createCallbackFn(callback);
if (typeof page != 'string') { if (typeof content == 'function') {
console.log('Print function requires an HTML string. Not an object'); scope = options;
return; callback = content;
options = {};
content = null;
} }
if (typeof params == 'string') { if (typeof options == 'function') {
params = { name: params }; scope = callback;
callback = options;
options = typeof content != 'string' ? content : {};
content = typeof content == 'string' ? content : null;
} }
params = this.mergeWithDefaults(params); var fn = this._createCallbackFn(callback, scope),
params = this._mergeWithDefaults(options || {});
if ([null, undefined, ''].indexOf(params.name) > -1) { exec(fn, null, 'Printer', 'print', [content, params]);
params.name = this.getDefaults().name;
}
exec(fn, null, 'Printer', 'print', [page, params]);
}; };
/** /**
* @private * The (platform specific) default settings.
* *
* Merge settings with default values. * @return [ Object ]
*
* @param {Object} options
* The custom options
*
* @retrun {Object}
* Default values merged
* with custom values
*/ */
exports.mergeWithDefaults = function (options) { exports.getDefaults = function () {
var map = Object.assign({}, this._defaults);
for (var key in map) {
if (Array.isArray(map[key])) {
map[key] = Array.from(map[key]);
} else
if (Object.prototype.isPrototypeOf(map[key])) {
map[key] = Object.assign({}, map[key]);
}
}
return map;
};
/**
* Overwrite default settings.
*
* @param [ Object ] newDefaults New default values.
*
* @return [ Void ]
*/
exports.setDefaults = function (newDefaults) {
Object.assign(this._defaults, newDefaults);
};
/**
* Merge custom properties with the default values.
*
* @param [ Object ] options Set of custom values.
*
* @retrun [ Object ]
*/
exports._mergeWithDefaults = function (options) {
var defaults = this.getDefaults(); var defaults = this.getDefaults();
if (options.bounds && !options.bounds.length) { if (options.bounds && !Array.isArray(options.bounds)) {
options.bounds = [ options.bounds = [
options.bounds.left || defaults.bounds[0], options.bounds.left || defaults.bounds[0],
options.bounds.top || defaults.bounds[1], options.bounds.top || defaults.bounds[1],
@ -197,38 +228,144 @@ exports.mergeWithDefaults = function (options) {
options.duplex = options.duplex ? 'long' : 'none'; options.duplex = options.duplex ? 'long' : 'none';
} }
for (var key in defaults) { Object.assign(defaults, options);
if (!options.hasOwnProperty(key)) {
options[key] = defaults[key];
continue;
}
if (typeof options[key] != typeof defaults[key]) { for (var key in defaults) {
if (defaults[key] !== null) {
options[key] = defaults[key];
} else {
delete options[key]; delete options[key];
} }
} }
options.meta = {
plugin: 'cordova-plugin-printer',
version: '0.8.0-alpha'
};
return options; return options;
}; };
/** /**
* @private * @private
* *
* Creates a callback, which will be executed within a specific scope. * Creates a callback, which will be executed
* within a specific scope.
* *
* @param {Function} callbackFn * @param [ Function ] callback The callback function.
* The callback function * @param [ Object ] scope The scope for the function.
* @param {Object} scope
* The scope for the function
* *
* @return {Function} * @return [ Function ] The new callback function
* The new callback function
*/ */
exports._createCallbackFn = function (callbackFn, scope) { exports._createCallbackFn = function (callback, scope) {
if (typeof callbackFn != 'function')
if (typeof callback !== 'function')
return; return;
return function () { return function () {
callbackFn.apply(scope || this, arguments); callback.apply(scope || this, arguments);
}; };
}; };
// Polyfill for Object.assign
if (typeof Object.assign != 'function') {
Object.assign = function(target) {
'use strict';
if (target == null) {
throw new TypeError('Cannot convert undefined or null to object');
}
target = Object(target);
for (var index = 1; index < arguments.length; index++) {
var source = arguments[index];
if (source != null) {
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
}
return target;
};
}
// Polyfill for Array.from
// Production steps of ECMA-262, Edition 6, 22.1.2.1
// Reference: https://people.mozilla.org/~jorendorff/es6-draft.html#sec-array.from
if (!Array.from) {
Array.from = (function () {
var toStr = Object.prototype.toString;
var isCallable = function (fn) {
return typeof fn === 'function' || toStr.call(fn) === '[object Function]';
};
var toInteger = function (value) {
var number = Number(value);
if (isNaN(number)) { return 0; }
if (number === 0 || !isFinite(number)) { return number; }
return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number));
};
var maxSafeInteger = Math.pow(2, 53) - 1;
var toLength = function (value) {
var len = toInteger(value);
return Math.min(Math.max(len, 0), maxSafeInteger);
};
// The length property of the from method is 1.
return function from(arrayLike/*, mapFn, thisArg */) {
// 1. Let C be the this value.
var C = this;
// 2. Let items be ToObject(arrayLike).
var items = Object(arrayLike);
// 3. ReturnIfAbrupt(items).
if (arrayLike == null) {
throw new TypeError("Array.from requires an array-like object - not null or undefined");
}
// 4. If mapfn is undefined, then let mapping be false.
var mapFn = arguments.length > 1 ? arguments[1] : void undefined;
var T;
if (typeof mapFn !== 'undefined') {
// 5. else
// 5. a If IsCallable(mapfn) is false, throw a TypeError exception.
if (!isCallable(mapFn)) {
throw new TypeError('Array.from: when provided, the second argument must be a function');
}
// 5. b. If thisArg was supplied, let T be thisArg; else let T be undefined.
if (arguments.length > 2) {
T = arguments[2];
}
}
// 10. Let lenValue be Get(items, "length").
// 11. Let len be ToLength(lenValue).
var len = toLength(items.length);
// 13. If IsConstructor(C) is true, then
// 13. a. Let A be the result of calling the [[Construct]] internal method of C with an argument list containing the single item len.
// 14. a. Else, Let A be ArrayCreate(len).
var A = isCallable(C) ? Object(new C(len)) : new Array(len);
// 16. Let k be 0.
var k = 0;
// 17. Repeat, while k < len… (also steps a - h)
var kValue;
while (k < len) {
kValue = items[k];
if (mapFn) {
A[k] = typeof T === 'undefined' ? mapFn(kValue, k) : mapFn.call(T, kValue, k);
} else {
A[k] = kValue;
}
k += 1;
}
// 18. Let putStatus be Put(A, "length", len, true).
A.length = len;
// 20. Return A.
return A;
};
}());
}