add fontsync pull and push

This commit is contained in:
kekee000
2016-03-20 21:10:36 +08:00
parent 043533118f
commit f11da19120
14 changed files with 181 additions and 66 deletions

View File

@@ -92,3 +92,5 @@ sh build.sh
23. 2016-2-25 增加字形导出svg和png功能.
24. 2016-3-7 将path的布尔操作库替换成paper.js的路径库.
25. 2016-3-20 增加字体同步的拉取和推送,增加自动更新同步版本.

View File

@@ -40,5 +40,6 @@ module.exports = exports = {
help: 'Help',
confirm: 'Confirm',
cancel: 'Cancel',
fontinfo: 'Font Info'
fontinfo: 'Font Info',
syncfromserver: 'Sync Font From Server'
};

View File

@@ -40,5 +40,6 @@ module.exports = exports = {
help: '帮助',
confirm: '确定',
cancel: '取消',
fontinfo: '字体信息'
fontinfo: '字体信息',
syncfromserver: '从服务器同步字体'
};

View File

@@ -20,7 +20,7 @@
* "fontName": "fonteditor", // 字体名称
* "hasNew": 1, // 如果有新数据则标记为1, 同时设置fontType, timestamp, ttf字段
* "timestamp": 12345678, // 新纪录时间戳unix timestamp 精确到毫秒
* "fontType": "ttf", // 新纪录类型
* "fontType": "ttf", // 新纪录类型默认为ttf字体
* "ttf": base64str // 新纪录的base64字体数据
* }
* }
@@ -54,8 +54,10 @@
*
* @author mengke01(kekee000@gmail.com)
*/
error_reporting(E_ALL ^ E_NOTICE);
define('SYNC_FILE', __DIR__ . '/list.md'); // 同步的文件
define('FONT_ROOT', __DIR__); // 同步字体的基础目录
define('SYNC_FILE', FONT_ROOT . '/list.md'); // 同步的文件
@@ -69,9 +71,13 @@ define('SYNC_FILE', __DIR__ . '/list.md'); // 同步的文件
function jsonp($status, $data = null, $statusInfo = null) {
$callback = $_GET['callback'];
$json = array(
'status' => $status,
'data' => $data,
'status' => $status
);
if (!empty($data)) {
$json['data'] = $data;
}
if (!empty($statusInfo)) {
$json['statusInfo'] = $statusInfo;
}
@@ -85,7 +91,14 @@ function jsonp($status, $data = null, $statusInfo = null) {
* @return number
*/
function getTimestamp() {
return intval(microtime(true) * 1000);
return floor(microtime(true) * 1000);
}
function getFontPath() {
// 根据具体情况设置fontpath
// $fontpath = FONT_ROOT . dirname($_SERVER["REQUEST_URI"]);
// return preg_replace('/\\\+/', '/', $fontpath);
return FONT_ROOT;
}
/**
@@ -134,6 +147,8 @@ function getSyncRecord() {
/**
* 保存同步的记录
*
* @param array $data 同步的记录列表
*/
function saveSyncRecord($data) {
file_put_contents(SYNC_FILE, json_encode($data));
@@ -152,9 +167,10 @@ function doPush() {
$ret = array(); // 记录成功的类型
$fontPath = getFontPath();
foreach (explode(',', $fontType) as $type) {
if (!empty($_POST[$type])) {
writeBase64File($_POST[$type], "${fontName}.${type}");
writeBase64File($_POST[$type], "${fontPath}/${fontName}.${type}");
$ret[] = $type;
}
}
@@ -162,7 +178,7 @@ function doPush() {
// 保存同步记录
$timestamp = getTimestamp();
$recordList = getSyncRecord();
$recordList[$fontName] = array(
$recordList["${fontPath}/${fontName}"] = array(
'user' => $_COOKIE['FONT_USER'],
'timestamp' => $timestamp,
'fontType' => $ret[0],
@@ -189,34 +205,35 @@ function doPush() {
*/
function doPull() {
$fontName = $_GET['fontName'];
$fontType = $_GET['fontType'];
$timestamp = empty($_GET['timestamp']) ? 0 : intval($_GET['timestamp']);
$fontType = $_GET['fontType']; // 默认拉取的为ttf字体
$timestamp = empty($_GET['timestamp']) ? 0 : floor($_GET['timestamp']);
if (empty($fontName)) {
jsonp(1, null, 'missing font field fontName!');
return;
}
$fontPath = getFontPath();
$recordList = getSyncRecord();
if (!empty($recordList[$fontName])) {
$record = $recordList[$fontName];
//var_dump($record);
// 最后一次提交不是当前用户,或者强制拉取
if (
($record['user'] != $_COOKIE['FONT_USER'] && $record['timestamp'] > $timestamp)
|| -1 === $timestamp
) {
if (!empty($recordList["${fontPath}/${fontName}"])) {
$record = $recordList["${fontPath}/${fontName}"];
}
else {
$record = array();
}
$fontFile = "${fontName}.${fontType}";
if (file_exists($fontFile)) {
$data = array(
'fontName' => $fontName,
'hasNew' => 1,
'timestamp' => $record['timestamp'],
'fontType' => $fontType,
);
$data[$fontType] = readBase64File($fontFile);
jsonp(0, $data);
return;
}
// 最后一次提交大于当前记录时间
if (-1 == $timestamp || $record['timestamp'] > $timestamp) {
$fontFile = "${fontPath}/${fontName}.${fontType}";
if (file_exists($fontFile)) {
$data = array(
'fontName' => $fontName,
'hasNew' => 1,
'timestamp' => empty($record['timestamp']) ? getTimestamp() : $record['timestamp'],
'fontType' => $fontType,
);
$data[$fontType] = readBase64File($fontFile);
jsonp(0, $data);
return;
}
}

View File

@@ -1 +1 @@
{"cicons":{"user":"3e60a8b0712c80d976fb3e917c658d4f","timestamp":1458308845195,"fontType":"ttf"}}
{"D:\\fonteditor\\demo\\sync\/fonteditor":{"user":"3e60a8b0712c80d976fb3e917c658d4f","timestamp":1458479047942,"fontType":"ttf"}}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -31,6 +31,7 @@
<li data-disabled="1" data-action="import" title="${lang.import_font_title}"><a>${lang.import_font}</a></li>
<li data-action="add-online"><a>${lang.onlinefont}</a></li>
<li data-action="add-url"><a>${lang.fonturl}</a></li>
<li data-action="sync-from-server"><a>${lang.syncfromserver}</a></li>
</ul>
</div>
<i class="split"></i>

1
list.md Normal file
View File

@@ -0,0 +1 @@
{"D:\/fonteditor\/fonteditor\/demo\/sync\/fonteditor":{"user":"3e60a8b0712c80d976fb3e917c658d4f","timestamp":1458405187581,"fontType":"ttf"}}

View File

@@ -48,17 +48,31 @@ define(
}, 20);
// 延迟同步函数
var fontDelaySync = lang.debounce(function (projectId, ttf, syncConfig) {
var fontDelaySync = lang.debounce(function (options) {
program.loading.show(i18n.lang.msg_syncing, 4000);
program.sync.addTask(projectId, ttf, syncConfig).then(function (data) {
if (data.newData) {
program.sync.addTask(options).then(function (data) {
if (options.newProject && data.newData) {
actions['new']({
ttf: data.newData,
config: {
sync: options.config
}
});
}
else if (options.type === 'push' && data.newData) {
program.ttfManager.ttf.set(data.newData);
program.ttfManager.fireChange(true);
program.project.update(options.projectId, data.newData).then(function () {
program.ttfManager.setState('saved');
});
}
program.loading.show(i18n.lang.msg_sync_success, 400);
}, function (data) {
console.warn(data.reason);
if (options.newProject && data.status === 500) {
alert(i18n.lang.msg_error_sync_font);
}
data.reason && console.warn(data.reason);
});
}, 500);
@@ -84,14 +98,15 @@ define(
}
},
'new': function () {
'new': function (options) {
if (program.ttfManager.isChanged() && !window.confirm(i18n.lang.msg_confirm_save_proj)) {
return;
}
program.ttfManager.set(getEmptyttfObject());
program.ttfManager.set((options && options.ttf) || getEmptyttfObject());
program.data.projectId = null;
// 建立项目 提示保存
actions.save();
actions.save(options);
},
'open': function () {
@@ -124,11 +139,32 @@ define(
}
},
'sync': function (projectId, ttf, syncConfig) {
fontDelaySync(program.data.projectId, ttf, syncConfig);
'sync-from-server': function () {
var SettingSync = settingSupport.sync;
// 从服务器同步字体
!new SettingSync({
onChange: function (setting) {
setting.timestamp = -1; // 配置强制拉取
fontDelaySync({
type: 'pull',
newProject: true,
config: setting
});
}
}).show({});
},
'save': function () {
'sync': function (projectId, ttf, config) {
// 推送字体
fontDelaySync({
type: 'push',
projectId: projectId,
ttf: ttf,
config: config
});
},
'save': function (options) {
if (program.ttfManager.get()) {
// 已经保存过的项目
var projectId = program.data.projectId;
@@ -151,8 +187,12 @@ define(
var name = program.ttfManager.get().name.fontFamily || '';
if ((name = window.prompt(i18n.lang.msg_input_proj_name, name))) {
name = string.encodeHTML(name);
program.project.add(name, program.ttfManager.get())
.then(function (id) {
options = options || {};
program.project.add(
name,
options.ttf || program.ttfManager.get(),
options.config
).then(function (id) {
program.data.projectId = id;
program.ttfManager.setState('new');
program.projectViewer.show(program.project.items(), id);

View File

@@ -40,7 +40,12 @@ define(
preview_title: 'Preview {%=fontFormat%} Format Font',
preview_first_step: 'Step 1: Use `{%=fontFamily%}` as font-face.',
preview_second_step: 'Step 2Define css styles with `{%=fontFamily%}`.',
preview_third_step: 'Step 3Set font unicode to icons on web page.'
preview_third_step: 'Step 3Set font unicode to icons on web page.',
msg_error_sync_font: 'Get sync font error!',
msg_error_sync_font_address: 'Font sync address not available!',
msg_has_new_font_version: 'Font `${fontName}` has new version, update now?',
msg_error_sync_font_version: 'Sync new font version error!'
};
}
);

View File

@@ -41,7 +41,12 @@ define(
preview_title: '预览{%=fontFormat%}格式字体',
preview_first_step: '第一步使用font-face声明字体',
preview_second_step: '第二步:定义使用{%=fontFamily%}的样式',
preview_third_step: '第三步:挑选相应图标并获取字体编码,应用于页面'
preview_third_step: '第三步:挑选相应图标并获取字体编码,应用于页面',
msg_error_sync_font: '无法获取同步字体!',
msg_error_sync_font_address: '字体同步地址不可用!',
msg_has_new_font_version: '字体`${fontName}`有新版本,是否同步新版本?',
msg_error_sync_font_version: '同步新版本出错!'
};
}
);

View File

@@ -29,6 +29,15 @@ define(
var project = {
/**
* 获取新项目的编号
*
* @return {string} 编号
*/
getId: function () {
return ('' + Date.now());
},
/**
* 获取现有项目列表
*
@@ -47,17 +56,23 @@ define(
*
* @param {string} name 项目名称
* @param {Object} ttf ttfObject
* @param {Object} config 当前的项目配置
*
* @return {Array} 现有项目列表
*/
add: function (name, ttf) {
add: function (name, ttf, config) {
var list = this.items();
var id = '' + Date.now();
list.push({
var id = (config && config.id) || this.getId();
var item = {
name: name,
id: id
});
};
// 设置当前项目的配置
if (config) {
item.config = config;
}
list.push(item);
storage.setItem('project-list', JSON.stringify(list));
if (projectDataStore) {
@@ -71,7 +86,7 @@ define(
return resolver.promise();
}
// 不支持 datastore 则使用localstorate存储
storage.setItem(id, JSON.stringify(ttf));
return Resolver.resolved(id);
},
@@ -81,9 +96,15 @@ define(
*
* @param {string} id 编号
* @param {Object} ttf ttf对象
* @param {Object} config 当前的项目配置
*
* @return {string} 项目编号
*/
update: function (id, ttf) {
update: function (id, ttf, config) {
// 设置当前项目的配置
if (config) {
this.updateConfig(id, config);
}
if (projectDataStore) {
var resolver = new Resolver();
@@ -97,6 +118,7 @@ define(
return resolver.promise();
}
// 不支持 datastore 则使用localstorate存储
storage.setItem(id, JSON.stringify(ttf));
return Resolver.resolved(id);
},

View File

@@ -8,6 +8,7 @@ define(
function (require) {
var i18n = require('../i18n/i18n');
var Resolver = require('common/promise');
var string = require('common/string');
var project = require('./project');
var writettf = require('./util/writettf');
var ttf2woff = require('fonteditor-core/ttf/ttf2woff');
@@ -16,7 +17,6 @@ define(
var loader = require('./loader');
var bytes2base64 = require('fonteditor-core/ttf/util/bytes2base64');
var base642bytes = require('fonteditor-core/ttf/util/base642bytes');
var SyncForm = require('./SyncForm');
var DEFAULT_FONTTYPE = 'ttf'; // 同步默认的字体类型
@@ -58,9 +58,10 @@ define(
function checkSync(syncConfig) {
var data = {
action: 'pull',
encode: 'base64',
fontName: syncConfig.name,
fontType: DEFAULT_FONTTYPE, // 暂时只接收ttf类型的字体
timestamp: syncConfig.timestamp || '',
timestamp: syncConfig.timestamp || 0
};
var resolver = new Resolver();
@@ -84,7 +85,7 @@ define(
resolver.resolve({});
}
else {
alert('同步地址不可用!');
alert(i18n.lang.msg_error_sync_font_address);
setSyncStatus(syncConfig.url, 0x1);
resolver.reject({
status: 404,
@@ -183,13 +184,22 @@ define(
/**
* 添加一个任务
* @param {Object} projectId 项目编号或者同步选项
* @param {?Object} ttf 字体对象
* @param {?Object} syncConfig 同步选项
*
* @param {Object} options 任务参数
* @param {string} options.type 同步类型push or pull
* @param {string} options.projectId 项目编号或者同步选项
* @param {?Object} options.ttf 字体对象
* @param {?Object} options.config 同步选项
*
* @return {Object} Promise对象
*/
exports.addTask = function (projectId, ttf, syncConfig) {
exports.addTask = function (options) {
var syncType = options.type || 'push';
var projectId = options.projectId;
var ttf = options.ttf;
var syncConfig = options.config;
options = null;
if (!syncConfig) {
syncConfig = project.getConfig(projectId).sync;
}
@@ -202,28 +212,38 @@ define(
var resolver = new Resolver();
checkSync(syncConfig).then(function (data) {
if (data.hasNew && window.confirm('字体`' + data.fontName + '`有新版本,是否同步新版本?')) {
if (data.hasNew && window.confirm(string.format(i18n.lang.msg_has_new_font_version, data.fontName))) {
if (data.fontType === DEFAULT_FONTTYPE && data[data.fontType]) {
// 解析后台传送过来的ttf字形
var ttfBuffer = new Int8Array(base642bytes(data[data.fontType])).buffer;
loader.load(ttfBuffer, {
type: 'ttf',
success: function (ttfObject) {
syncConfig.timestamp = data.timestamp || 0;
resolver.resolve({
timestamp: data.timestamp,
newData: ttfObject
});
},
error: function () {
alert('同步新版本出错!');
alert(i18n.lang.msg_error_sync_font_version);
}
});
}
else {
alert('同步新版本出错!');
alert(i18n.lang.msg_error_sync_font_version);
}
return;
}
// 拉取模式下用户取消或者没有新数据,则返回
if (syncType === 'pull') {
resolver.reject({
status: data.hasNew ? 200 : 500
});
return;
}
// 获取当前推送的ttf如果没有则从本地存储中获取
if (!ttf) {
project.get(projectId).then(function (data) {