Merge pull request #133 from owncloud/member-management
Member management
This commit is contained in:
commit
5bdad7be17
@ -50,50 +50,6 @@ try{
|
||||
|
||||
$command = $request->getParam('command');
|
||||
switch ($command){
|
||||
case 'query_memberdata_list':
|
||||
$ids = $request->getParam('args/member_ids');
|
||||
|
||||
$member = new Db_Member();
|
||||
$members = $member->getCollectionBy('member_id', $ids);
|
||||
|
||||
$response["memberdata_list"] = array_map(
|
||||
function($x){
|
||||
$x['display_name'] = \OCP\User::getDisplayName($x['uid']);
|
||||
|
||||
// Do we have OC_Avatar in out disposal?
|
||||
if (!class_exists('\OC_Avatar') || \OC_Config::getValue('enable_avatars', true) !== true){
|
||||
//$x['avatar_url'] = \OCP\Util::linkToRoute('documents_user_avatar');
|
||||
$x['avatar_url'] = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAAAAACH5BAAAAAAALAAAAAABAAEAAAICTAEAOw==';
|
||||
} else {
|
||||
// https://github.com/owncloud/documents/issues/51
|
||||
// Temporary stub
|
||||
|
||||
$x['avatar_url'] = $x['uid'];
|
||||
|
||||
/*
|
||||
$avatar = new \OC_Avatar($x['uid']);
|
||||
$image = $avatar->get(64);
|
||||
// User has an avatar
|
||||
if ($image instanceof \OC_Image) {
|
||||
$x['avatar_url'] = \OC_Helper::linkToRoute(
|
||||
'core_avatar_get',
|
||||
array( 'user' => $x['uid'], 'size' => 64)
|
||||
) . '?requesttoken=' . \OC::$session->get('requesttoken');
|
||||
} else {
|
||||
//shortcircuit if it's not an image
|
||||
$x['avatar_url'] = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAAAAACH5BAAAAAAALAAAAAABAAEAAAICTAEAOw==';
|
||||
}
|
||||
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
return $x;
|
||||
},
|
||||
$members
|
||||
);
|
||||
|
||||
break;
|
||||
case 'sync_ops':
|
||||
$seqHead = (string) $request->getParam('args/seq_head');
|
||||
if (!is_null($seqHead)){
|
||||
|
@ -32,6 +32,8 @@ class UserController extends Controller{
|
||||
$memberData = $member->getData();
|
||||
if ($memberData['es_id']===$esId){
|
||||
$member->deactivate(array($args['member_id']));
|
||||
$op = new Db_Op();
|
||||
$op->removeMember($esId, $args['member_id']);
|
||||
}
|
||||
}
|
||||
\OCP\JSON::success();
|
||||
|
31
js/3rdparty/webodf/editor/Editor.js
vendored
31
js/3rdparty/webodf/editor/Editor.js
vendored
@ -124,7 +124,20 @@ define("webodf/editor/Editor", [
|
||||
* @return {undefined}
|
||||
*/
|
||||
this.openDocument = function (docUrl, memberId, editorReadyCallback) {
|
||||
initDocLoading(docUrl, memberId, editorReadyCallback);
|
||||
initDocLoading(docUrl, memberId, function () {
|
||||
runtime.loadClass("ops.OpAddMember");
|
||||
var op = new ops.OpAddMember();
|
||||
op.init({
|
||||
memberid: memberId,
|
||||
setProperties: {
|
||||
fullName: runtime.tr("Unknown Author"),
|
||||
color: "black",
|
||||
imageUrl: "avatar-joe.png"
|
||||
}
|
||||
});
|
||||
session.enqueue([op]);
|
||||
editorReadyCallback();
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
@ -134,6 +147,14 @@ define("webodf/editor/Editor", [
|
||||
*/
|
||||
this.closeDocument = function (callback) {
|
||||
runtime.assert(session, "session should exist here.");
|
||||
runtime.loadClass("ops.OpRemoveMember");
|
||||
|
||||
var op = new ops.OpRemoveMember();
|
||||
op.init({
|
||||
memberid: editorSession.sessionController.getInputMemberId()
|
||||
});
|
||||
session.enqueue([op]);
|
||||
|
||||
session.close(function (err) {
|
||||
if (err) {
|
||||
callback(err);
|
||||
@ -195,16 +216,12 @@ define("webodf/editor/Editor", [
|
||||
*/
|
||||
this.openSession = function (sessionId, memberId, editorReadyCallback) {
|
||||
initDocLoading(server.getGenesisUrl(sessionId), memberId, function () {
|
||||
var opRouter, memberModel;
|
||||
// overwrite router and member model
|
||||
// overwrite router
|
||||
// TODO: serverFactory should be a backendFactory,
|
||||
// and there should be a backendFactory for local editing
|
||||
opRouter = serverFactory.createOperationRouter(sessionId, memberId, server, odfCanvas.odfContainer());
|
||||
var opRouter = serverFactory.createOperationRouter(sessionId, memberId, server, odfCanvas.odfContainer());
|
||||
session.setOperationRouter(opRouter);
|
||||
|
||||
memberModel = serverFactory.createMemberModel(sessionId, server);
|
||||
session.setMemberModel(memberModel);
|
||||
|
||||
opRouter.requestReplay(function done() {
|
||||
editorReadyCallback();
|
||||
});
|
||||
|
44
js/3rdparty/webodf/editor/EditorSession.js
vendored
44
js/3rdparty/webodf/editor/EditorSession.js
vendored
@ -82,8 +82,11 @@ define("webodf/editor/EditorSession", [
|
||||
domUtils = new core.DomUtils(),
|
||||
eventNotifier = new core.EventNotifier([
|
||||
EditorSession.signalMemberAdded,
|
||||
EditorSession.signalMemberUpdated,
|
||||
EditorSession.signalMemberRemoved,
|
||||
EditorSession.signalCursorAdded,
|
||||
EditorSession.signalCursorMoved,
|
||||
EditorSession.signalCursorRemoved,
|
||||
EditorSession.signalParagraphChanged,
|
||||
EditorSession.signalCommonStyleCreated,
|
||||
EditorSession.signalCommonStyleDeleted,
|
||||
@ -211,13 +214,25 @@ define("webodf/editor/EditorSession", [
|
||||
paragraphRange.detach();
|
||||
}
|
||||
|
||||
function onMemberAdded(member) {
|
||||
self.emit(EditorSession.signalMemberAdded, member.getMemberId());
|
||||
}
|
||||
|
||||
function onMemberUpdated(member) {
|
||||
self.emit(EditorSession.signalMemberUpdated, member.getMemberId());
|
||||
}
|
||||
|
||||
function onMemberRemoved(memberId) {
|
||||
self.emit(EditorSession.signalMemberRemoved, memberId);
|
||||
}
|
||||
|
||||
function onCursorAdded(cursor) {
|
||||
self.emit(EditorSession.signalMemberAdded, cursor.getMemberId());
|
||||
self.emit(EditorSession.signalCursorAdded, cursor.getMemberId());
|
||||
trackCursor(cursor);
|
||||
}
|
||||
|
||||
function onCursorRemoved(memberId) {
|
||||
self.emit(EditorSession.signalMemberRemoved, memberId);
|
||||
self.emit(EditorSession.signalCursorRemoved, memberId);
|
||||
}
|
||||
|
||||
function onCursorMoved(cursor) {
|
||||
@ -267,14 +282,6 @@ define("webodf/editor/EditorSession", [
|
||||
eventNotifier.unsubscribe(eventid, cb);
|
||||
};
|
||||
|
||||
this.getMemberDetailsAndUpdates = function (memberId, subscriber) {
|
||||
return session.getMemberModel().getMemberDetailsAndUpdates(memberId, subscriber);
|
||||
};
|
||||
|
||||
this.unsubscribeMemberDetailsUpdates = function (memberId, subscriber) {
|
||||
return session.getMemberModel().unsubscribeMemberDetailsUpdates(memberId, subscriber);
|
||||
};
|
||||
|
||||
this.getCursorPosition = function () {
|
||||
return odtDocument.getCursorPosition(localMemberId);
|
||||
};
|
||||
@ -513,6 +520,14 @@ define("webodf/editor/EditorSession", [
|
||||
self.sessionController.getImageManager().insertImage(mimetype, content, width, height);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {!string} memberId
|
||||
* @return {?ops.Member}
|
||||
*/
|
||||
this.getMember = function (memberId) {
|
||||
return odtDocument.getMember(memberId);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {!function(!Object=)} callback, passing an error object in case of error
|
||||
* @return {undefined}
|
||||
@ -522,6 +537,9 @@ define("webodf/editor/EditorSession", [
|
||||
|
||||
head.removeChild(fontStyles);
|
||||
|
||||
odtDocument.unsubscribe(ops.OdtDocument.signalMemberAdded, onMemberAdded);
|
||||
odtDocument.unsubscribe(ops.OdtDocument.signalMemberUpdated, onMemberUpdated);
|
||||
odtDocument.unsubscribe(ops.OdtDocument.signalMemberRemoved, onMemberRemoved);
|
||||
odtDocument.unsubscribe(ops.OdtDocument.signalCursorAdded, onCursorAdded);
|
||||
odtDocument.unsubscribe(ops.OdtDocument.signalCursorRemoved, onCursorRemoved);
|
||||
odtDocument.unsubscribe(ops.OdtDocument.signalCursorMoved, onCursorMoved);
|
||||
@ -578,6 +596,9 @@ define("webodf/editor/EditorSession", [
|
||||
self.availableFonts = getAvailableFonts();
|
||||
selectionViewManager.registerCursor(shadowCursor, true);
|
||||
// Custom signals, that make sense in the Editor context. We do not want to expose webodf's ops signals to random bits of the editor UI.
|
||||
odtDocument.subscribe(ops.OdtDocument.signalMemberAdded, onMemberAdded);
|
||||
odtDocument.subscribe(ops.OdtDocument.signalMemberUpdated, onMemberUpdated);
|
||||
odtDocument.subscribe(ops.OdtDocument.signalMemberRemoved, onMemberRemoved);
|
||||
odtDocument.subscribe(ops.OdtDocument.signalCursorAdded, onCursorAdded);
|
||||
odtDocument.subscribe(ops.OdtDocument.signalCursorRemoved, onCursorRemoved);
|
||||
odtDocument.subscribe(ops.OdtDocument.signalCursorMoved, onCursorMoved);
|
||||
@ -592,7 +613,10 @@ define("webodf/editor/EditorSession", [
|
||||
};
|
||||
|
||||
/**@const*/EditorSession.signalMemberAdded = "memberAdded";
|
||||
/**@const*/EditorSession.signalMemberUpdated = "memberUpdated";
|
||||
/**@const*/EditorSession.signalMemberRemoved = "memberRemoved";
|
||||
/**@const*/EditorSession.signalCursorAdded = "cursorAdded";
|
||||
/**@const*/EditorSession.signalCursorRemoved = "cursorRemoved";
|
||||
/**@const*/EditorSession.signalCursorMoved = "cursorMoved";
|
||||
/**@const*/EditorSession.signalParagraphChanged = "paragraphChanged";
|
||||
/**@const*/EditorSession.signalCommonStyleCreated = "styleCreated";
|
||||
|
29
js/3rdparty/webodf/editor/MemberListView.js
vendored
29
js/3rdparty/webodf/editor/MemberListView.js
vendored
@ -73,14 +73,14 @@ define("webodf/editor/MemberListView",
|
||||
while (node) {
|
||||
if (node.localName === "img") {
|
||||
// update avatar image
|
||||
node.src = memberDetails.imageurl;
|
||||
node.src = memberDetails.imageUrl;
|
||||
// update border color
|
||||
node.style.borderColor = memberDetails.color;
|
||||
} else if (node.localName === "span" && memberDetails.imageurl){
|
||||
$(node).avatar(memberDetails.imageurl, 60);
|
||||
} else if (node.localName === "span" && memberDetails.imageUrl){
|
||||
$(node).avatar(memberDetails.imageUrl, 60);
|
||||
node.style.borderColor = memberDetails.color;
|
||||
} else if (node.localName === "div") {
|
||||
node.setAttribute('fullname', memberDetails.fullname);
|
||||
node.setAttribute('fullname', memberDetails.fullName);
|
||||
}
|
||||
node = node.nextSibling;
|
||||
}
|
||||
@ -142,8 +142,21 @@ define("webodf/editor/MemberListView",
|
||||
* @return {undefined}
|
||||
*/
|
||||
function addMember(memberId) {
|
||||
var member = editorSession.getMember(memberId),
|
||||
properties = member.getProperties();
|
||||
createAvatarButton(memberId);
|
||||
editorSession.getMemberDetailsAndUpdates(memberId, updateAvatarButton);
|
||||
updateAvatarButton(memberId, properties);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {!string} memberId
|
||||
* @return {undefined}
|
||||
*/
|
||||
function updateMember(memberId) {
|
||||
var member = editorSession.getMember(memberId),
|
||||
properties = member.getProperties();
|
||||
|
||||
updateAvatarButton(memberId, properties);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -151,7 +164,6 @@ define("webodf/editor/MemberListView",
|
||||
* @return {undefined}
|
||||
*/
|
||||
function removeMember(memberId) {
|
||||
editorSession.unsubscribeMemberDetailsUpdates(memberId, updateAvatarButton);
|
||||
removeAvatarButton(memberId);
|
||||
}
|
||||
|
||||
@ -161,14 +173,12 @@ define("webodf/editor/MemberListView",
|
||||
if (editorSession) {
|
||||
// unsubscribe from editorSession
|
||||
editorSession.unsubscribe(EditorSession.signalMemberAdded, addMember);
|
||||
editorSession.unsubscribe(EditorSession.signalMemberUpdated, updateMember);
|
||||
editorSession.unsubscribe(EditorSession.signalMemberRemoved, removeMember);
|
||||
// remove all current avatars
|
||||
node = memberListDiv.firstChild;
|
||||
while (node) {
|
||||
nextNode = node.nextSibling;
|
||||
if (node.memberId) {
|
||||
editorSession.unsubscribeMemberDetailsUpdates(node.memberId, updateAvatarButton);
|
||||
}
|
||||
memberListDiv.removeChild(node);
|
||||
node = nextNode;
|
||||
}
|
||||
@ -185,6 +195,7 @@ define("webodf/editor/MemberListView",
|
||||
editorSession = session;
|
||||
if (editorSession) {
|
||||
editorSession.subscribe(EditorSession.signalMemberAdded, addMember);
|
||||
editorSession.subscribe(EditorSession.signalMemberUpdated, updateMember);
|
||||
editorSession.subscribe(EditorSession.signalMemberRemoved, removeMember);
|
||||
}
|
||||
};
|
||||
|
@ -57,13 +57,6 @@ ServerFactory.prototype.createServer = function () {"use strict"; };
|
||||
*/
|
||||
ServerFactory.prototype.createOperationRouter = function (sessionId, memberId, server, odfContainer) {"use strict"; };
|
||||
|
||||
/**
|
||||
* @param {!string} sessionId
|
||||
* @param {!ops.Server} server
|
||||
* @return {!ops.MemberModel}
|
||||
*/
|
||||
ServerFactory.prototype.createMemberModel = function (sessionId, server) {"use strict"; };
|
||||
|
||||
/**
|
||||
* @param {!ops.Server} server
|
||||
* @return {!SessionList}
|
||||
|
@ -27,10 +27,9 @@
|
||||
|
||||
define("webodf/editor/server/owncloud/ServerFactory", [
|
||||
"webodf/editor/server/pullbox/Server",
|
||||
"webodf/editor/server/pullbox/MemberModel",
|
||||
"webodf/editor/server/pullbox/OperationRouter",
|
||||
"webodf/editor/server/pullbox/SessionList"],
|
||||
function (PullBoxServer, PullBoxMemberModel, PullBoxOperationRouter, PullBoxSessionList) {
|
||||
function (PullBoxServer, PullBoxOperationRouter, PullBoxSessionList) {
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
@ -54,9 +53,6 @@ define("webodf/editor/server/owncloud/ServerFactory", [
|
||||
this.createOperationRouter = function (sid, mid, server, odfContainer) {
|
||||
return new PullBoxOperationRouter(sid, mid, server, odfContainer);
|
||||
};
|
||||
this.createMemberModel = function (sid, server) {
|
||||
return new PullBoxMemberModel(sid, server);
|
||||
};
|
||||
this.createSessionList = function (server) {
|
||||
return new PullBoxSessionList(server);
|
||||
};
|
||||
|
@ -1,279 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
|
||||
*
|
||||
* @licstart
|
||||
* This file is part of WebODF.
|
||||
*
|
||||
* WebODF is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License (GNU AGPL)
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* WebODF is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with WebODF. If not, see <http://www.gnu.org/licenses/>.
|
||||
* @licend
|
||||
*
|
||||
* @source: http://www.webodf.org/
|
||||
* @source: https://github.com/kogmbh/WebODF/
|
||||
*/
|
||||
|
||||
/*global runtime, ops*/
|
||||
|
||||
define("webodf/editor/server/pullbox/MemberModel", [], function () {
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @implements ops.MemberModel
|
||||
*/
|
||||
return function PullBoxMemberModel(sessionId, server) {
|
||||
|
||||
var cachedMemberData = {},
|
||||
memberDataSubscribers = {},
|
||||
isServerPullingActivated = false,
|
||||
isServerPullingOpen = true,
|
||||
serverPullingTimeoutId = null,
|
||||
isInstantPullingRequested = false,
|
||||
isPulling = false,
|
||||
/**@const*/pullingIntervall = 20000;
|
||||
|
||||
|
||||
/**
|
||||
* @param {!Object} memberData
|
||||
*/
|
||||
function cacheMemberDatum(memberData) {
|
||||
var subscribers,
|
||||
i;
|
||||
|
||||
// notify all subscribers who are interested in this data
|
||||
subscribers = memberDataSubscribers[memberData.memberid];
|
||||
if (subscribers) {
|
||||
// cache
|
||||
cachedMemberData[memberData.memberid] = memberData;
|
||||
|
||||
for (i = 0; i < subscribers.length; i += 1) {
|
||||
subscribers[i](memberData.memberid, memberData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function pullMemberData() {
|
||||
var i,
|
||||
memberIds = Object.keys(memberDataSubscribers);
|
||||
|
||||
if (!isServerPullingOpen || isPulling) {
|
||||
return;
|
||||
}
|
||||
|
||||
// no more timeout or instant pull request in any case
|
||||
serverPullingTimeoutId = null;
|
||||
isInstantPullingRequested = false;
|
||||
// set lock
|
||||
isPulling = true;
|
||||
|
||||
runtime.log("member-list request for : " + memberIds.join(","));
|
||||
|
||||
server.call({
|
||||
command: 'query_memberdata_list',
|
||||
args: {
|
||||
es_id: sessionId,
|
||||
member_ids: memberIds
|
||||
}
|
||||
}, function(responseData) {
|
||||
var response = /**@type {{memberdata_list:Array.<{uid,member_id,display_name,avatar_url,color}>}}*/(runtime.fromJson(responseData)),
|
||||
memberDataList,
|
||||
newMemberData, oldMemberData;
|
||||
|
||||
// unlock
|
||||
isPulling = false;
|
||||
|
||||
// meanwhile closed/disactivated?
|
||||
if (!isServerPullingOpen || !isServerPullingActivated) {
|
||||
return;
|
||||
}
|
||||
|
||||
runtime.log("member-list reply: " + responseData);
|
||||
|
||||
if (response.hasOwnProperty("memberdata_list")) {
|
||||
|
||||
// add/update with all delivered memberdata
|
||||
memberDataList = response.memberdata_list;
|
||||
for (i = 0; i < memberDataList.length; i+=1) {
|
||||
newMemberData = {
|
||||
memberid: memberDataList[i].member_id,
|
||||
fullname: memberDataList[i].display_name,
|
||||
imageurl: memberDataList[i].avatar_url,
|
||||
color: memberDataList[i].color
|
||||
};
|
||||
|
||||
oldMemberData = cachedMemberData.hasOwnProperty(newMemberData.memberid) ? cachedMemberData[newMemberData.memberid] : null;
|
||||
if (!oldMemberData ||
|
||||
oldMemberData.fullname !== newMemberData.fullname ||
|
||||
oldMemberData.imageurl !== newMemberData.imageurl ||
|
||||
oldMemberData.color !== newMemberData.color) {
|
||||
cacheMemberDatum(newMemberData);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
runtime.log("Meh, memberdata list broken: " + responseData);
|
||||
}
|
||||
|
||||
// trigger the next pulling
|
||||
if (isInstantPullingRequested) {
|
||||
pullMemberData();
|
||||
} else {
|
||||
serverPullingTimeoutId = runtime.setTimeout(pullMemberData, pullingIntervall);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Activates the pulling
|
||||
* @return {undefined}
|
||||
*/
|
||||
function pullNewMemberData() {
|
||||
// cancel any running pulling timeout
|
||||
if (serverPullingTimeoutId !== null) {
|
||||
runtime.clearTimeout(serverPullingTimeoutId);
|
||||
}
|
||||
|
||||
isInstantPullingRequested = true;
|
||||
isServerPullingActivated = true;
|
||||
|
||||
pullMemberData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deactivates the pulling if there are no more subscribers
|
||||
* @return {undefined}
|
||||
*/
|
||||
function deactivatePeriodicMemberDataPulling() {
|
||||
var key;
|
||||
|
||||
if (!isServerPullingActivated) {
|
||||
return;
|
||||
}
|
||||
|
||||
// check if there is no more subscription
|
||||
for(key in memberDataSubscribers) {
|
||||
if (memberDataSubscribers.hasOwnProperty(key)) {
|
||||
// still subscribers, cannot deactivate yet
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
isServerPullingActivated = false;
|
||||
// cancel any running pulling timeout
|
||||
if (serverPullingTimeoutId !== null) {
|
||||
runtime.clearTimeout(serverPullingTimeoutId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* callback is called as soon as the memberdata is available and after that
|
||||
* on every memberdata update.
|
||||
* a parameter `null` passed to the callback means that the member is finally
|
||||
* not known.
|
||||
*
|
||||
* @param {!string} memberId
|
||||
* @param {!function(!string, ?Object)} subscriber
|
||||
* @return {undefined}
|
||||
*/
|
||||
this.getMemberDetailsAndUpdates = function (memberId, subscriber) {
|
||||
var /**@type{Object}*/
|
||||
memberData = cachedMemberData[memberId],
|
||||
subscribers = memberDataSubscribers[memberId] || [],
|
||||
i;
|
||||
memberDataSubscribers[memberId] = subscribers;
|
||||
|
||||
runtime.assert(subscriber !== undefined, "missing callback");
|
||||
|
||||
// detect double subscription
|
||||
for (i=0; i<subscribers.length; i+=1) {
|
||||
if (subscribers[i] === subscriber) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i < subscribers.length) {
|
||||
// already subscribed
|
||||
runtime.log("double subscription request for "+memberId+" in PullBoxMemberModel::getMemberDetailsAndUpdates");
|
||||
} else {
|
||||
// subscribe
|
||||
subscribers.push(subscriber);
|
||||
// query data from server, if not done yet
|
||||
if (subscribers.length === 1) {
|
||||
// TODO: only fetch data for memberId here
|
||||
pullNewMemberData();
|
||||
}
|
||||
}
|
||||
|
||||
if (memberData) {
|
||||
// data available from cache
|
||||
subscriber(memberId, memberData);
|
||||
} else {
|
||||
// pass temporary data
|
||||
subscriber(memberId, {
|
||||
memberid: memberId,
|
||||
fullname: "Unknown",
|
||||
color: "black",
|
||||
imageurl: ""
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* getMemberDetailsAndUpdates subscribes a callback for updates on member details.
|
||||
* this function undoes this subscription.
|
||||
*
|
||||
* @param {!string} memberId
|
||||
* @param {!function(!string, ?Object)} subscriber
|
||||
* @return {undefined}
|
||||
*/
|
||||
this.unsubscribeMemberDetailsUpdates = function (memberId, subscriber) {
|
||||
var i,
|
||||
subscribers = memberDataSubscribers[memberId];
|
||||
|
||||
runtime.assert(subscriber!==undefined, "missing subscriber parameter or null");
|
||||
runtime.assert(subscribers,
|
||||
"tried to unsubscribe when no one is subscribed ('" + memberId + "')");
|
||||
if (subscribers) {
|
||||
for (i=0; i<subscribers.length; i+=1) {
|
||||
if (subscribers[i] === subscriber) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
runtime.assert((i < subscribers.length),
|
||||
"tried to unsubscribe when not subscribed for memberId '" + memberId + "'");
|
||||
|
||||
subscribers.splice(i,1);
|
||||
|
||||
// clean up
|
||||
if (subscribers.length === 0) {
|
||||
runtime.log("no more subscribers for: "+memberId);
|
||||
delete memberDataSubscribers[memberId];
|
||||
delete cachedMemberData[memberId];
|
||||
deactivatePeriodicMemberDataPulling();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Requests a gracefull shutdown of the Member Model
|
||||
* No more network activity is necessary.
|
||||
*/
|
||||
this.close = function (cb) {
|
||||
isServerPullingOpen = false;
|
||||
cb();
|
||||
};
|
||||
|
||||
runtime.assert(server.networkStatus() === "ready", "network not ready");
|
||||
};
|
||||
});
|
@ -410,8 +410,8 @@ runtime.log("OperationRouter: instant opsSync requested");
|
||||
var timedOp,
|
||||
opspec = op.spec();
|
||||
|
||||
// note if any local ops modified TODO: find less fragile way, perhaps have the operationFactory check it?
|
||||
hasPushedModificationOps = hasPushedModificationOps || !/^(AddCursor|MoveCursor|RemoveCursor)$/.test(opspec.optype);
|
||||
// note if any local ops modified
|
||||
hasPushedModificationOps = hasPushedModificationOps || op.isEdit;
|
||||
|
||||
// apply locally
|
||||
opspec.timestamp = (new Date()).getTime();
|
||||
|
@ -57,9 +57,7 @@ define("webodf/editor/server/pullbox/Server", [], function () {
|
||||
*/
|
||||
function call(message, cb) {
|
||||
var xhr = new XMLHttpRequest(),
|
||||
byteArrayWriter = new core.ByteArrayWriter("utf8"),
|
||||
messageString = JSON.stringify(message),
|
||||
data;
|
||||
messageString = JSON.stringify(message);
|
||||
|
||||
function handleResult() {
|
||||
if (xhr.readyState === 4) {
|
||||
@ -73,9 +71,6 @@ define("webodf/editor/server/pullbox/Server", [], function () {
|
||||
}
|
||||
runtime.log("Sending message to server: "+messageString);
|
||||
// create body data for request from metadata and payload
|
||||
byteArrayWriter.appendString(messageString);
|
||||
// byteArrayWriter.appendByteArray(zipData);
|
||||
data = byteArrayWriter.getByteArray();
|
||||
|
||||
// do the request
|
||||
xhr.open('POST', args.url, true);
|
||||
@ -83,20 +78,8 @@ runtime.log("Sending message to server: "+messageString);
|
||||
xhr.setRequestHeader("requesttoken", token);
|
||||
}
|
||||
xhr.onreadystatechange = handleResult;
|
||||
// ArrayBufferView will have an ArrayBuffer property, in WebKit, XHR can send()
|
||||
// an ArrayBuffer, In Firefox, one must use sendAsBinary with a string
|
||||
if (data.buffer && !xhr.sendAsBinary) {
|
||||
data = data.buffer; // webkit supports sending an ArrayBuffer
|
||||
} else {
|
||||
// encode into a string, this works in FireFox >= 3
|
||||
data = runtime.byteArrayToString(data, "binary");
|
||||
}
|
||||
try {
|
||||
if (xhr.sendAsBinary) {
|
||||
xhr.sendAsBinary(data);
|
||||
} else {
|
||||
xhr.send(data);
|
||||
}
|
||||
xhr.send(messageString);
|
||||
} catch (e) {
|
||||
runtime.log("Problem with calling server: " + e + " " + data);
|
||||
cb(e.message);
|
||||
|
@ -27,10 +27,9 @@
|
||||
|
||||
define("webodf/editor/server/pullbox/ServerFactory", [
|
||||
"webodf/editor/server/pullbox/Server",
|
||||
"webodf/editor/server/pullbox/MemberModel",
|
||||
"webodf/editor/server/pullbox/OperationRouter",
|
||||
"webodf/editor/server/pullbox/SessionList"],
|
||||
function (PullBoxServer, PullBoxMemberModel, PullBoxOperationRouter, PullBoxSessionList) {
|
||||
function (PullBoxServer, PullBoxOperationRouter, PullBoxSessionList) {
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
@ -44,9 +43,6 @@ define("webodf/editor/server/pullbox/ServerFactory", [
|
||||
this.createOperationRouter = function (sid, mid, server, odfContainer) {
|
||||
return new PullBoxOperationRouter(sid, mid, server, odfContainer);
|
||||
};
|
||||
this.createMemberModel = function (sid, server) {
|
||||
return new PullBoxMemberModel(sid, server);
|
||||
};
|
||||
this.createSessionList = function (server) {
|
||||
return new PullBoxSessionList(server);
|
||||
};
|
||||
|
18
js/3rdparty/webodf/editor/widgets/annotation.js
vendored
18
js/3rdparty/webodf/editor/widgets/annotation.js
vendored
@ -48,7 +48,7 @@ define("webodf/editor/widgets/annotation", [
|
||||
var self = this,
|
||||
widget = {},
|
||||
addAnnotationButton,
|
||||
annotationManager;
|
||||
annotationController;
|
||||
|
||||
|
||||
addAnnotationButton = new Button({
|
||||
@ -57,8 +57,8 @@ define("webodf/editor/widgets/annotation", [
|
||||
showLabel: false,
|
||||
iconClass: 'dijitIconBookmark',
|
||||
onClick: function () {
|
||||
if (annotationManager) {
|
||||
annotationManager.addAnnotation();
|
||||
if (annotationController) {
|
||||
annotationController.addAnnotation();
|
||||
self.onToolDone();
|
||||
}
|
||||
}
|
||||
@ -83,14 +83,14 @@ define("webodf/editor/widgets/annotation", [
|
||||
}
|
||||
|
||||
this.setEditorSession = function (session) {
|
||||
if (annotationManager) {
|
||||
annotationManager.unsubscribe(gui.AnnotationManager.annotatableChanged, onAnnotatableChanged);
|
||||
if (annotationController) {
|
||||
annotationController.unsubscribe(gui.AnnotationController.annotatableChanged, onAnnotatableChanged);
|
||||
}
|
||||
annotationManager = session && session.sessionController.getAnnotationManager();
|
||||
if (annotationManager) {
|
||||
annotationManager.subscribe(gui.AnnotationManager.annotatableChanged, onAnnotatableChanged);
|
||||
annotationController = session && session.sessionController.getAnnotationController();
|
||||
if (annotationController) {
|
||||
annotationController.subscribe(gui.AnnotationController.annotatableChanged, onAnnotatableChanged);
|
||||
}
|
||||
onAnnotatableChanged(annotationManager && annotationManager.isAnnotatable());
|
||||
onAnnotatableChanged(annotationController && annotationController.isAnnotatable());
|
||||
};
|
||||
|
||||
this.onToolDone = function () {};
|
||||
|
1867
js/3rdparty/webodf/webodf-debug.js
vendored
1867
js/3rdparty/webodf/webodf-debug.js
vendored
File diff suppressed because one or more lines are too long
2148
js/3rdparty/webodf/webodf.js
vendored
2148
js/3rdparty/webodf/webodf.js
vendored
File diff suppressed because one or more lines are too long
@ -84,11 +84,34 @@ class Db_Op extends Db {
|
||||
}
|
||||
|
||||
public function removeCursor($esId, $memberId){
|
||||
$op = '{"optype":"RemoveCursor","memberid":"'. $memberId .'","reason":"server-idle","timestamp":'. time() .'}';
|
||||
$this->insertOp($esId, $op);
|
||||
}
|
||||
|
||||
public function addMember($esId, $memberId, $fullName, $color, $imageUrl){
|
||||
$op = '{"optype":"AddMember","memberid":"'. $memberId .'","timestamp":"'. time() .'", "setProperties":{"fullName":"'. $fullName .'","color":"'. $color .'","imageUrl":"'. $imageUrl .'"}}';
|
||||
$this->insertOp($esId, $op);
|
||||
}
|
||||
|
||||
public function removeMember($esId, $memberId){
|
||||
$op ='{"optype":"RemoveMember","memberid":"'. $memberId .'","timestamp":'. time() .'}';
|
||||
$this->insertOp($esId, $op);
|
||||
}
|
||||
|
||||
public function updateMember($esId, $memberId, $fullName, $color, $imageUrl){
|
||||
//TODO: Follow the spec https://github.com/kogmbh/WebODF/blob/master/webodf/lib/ops/OpUpdateMember.js#L95
|
||||
$op = '{"optype":"UpdateMember","memberid":"'. $memberId .'","fullName":"'. $fullName .'","color":"'. $color .'","imageUrl":"'. $imageUrl .'","timestamp":'. time() .'}'
|
||||
;
|
||||
$this->insertOp($esId, $op);
|
||||
}
|
||||
|
||||
protected function insertOp($esId, $op){
|
||||
$op = new Db_Op(array(
|
||||
$esId,
|
||||
0,
|
||||
'{"optype":"RemoveCursor","memberid":"'. $memberId .'","reason":"server-idle","timestamp":'. time() .'}'
|
||||
$op
|
||||
));
|
||||
$op->insert();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -64,14 +64,52 @@ class Db_Session extends \OCA\Documents\Db {
|
||||
->getData()
|
||||
;
|
||||
|
||||
$memberColor = Helper::getRandomColor();
|
||||
|
||||
$member = new Db_Member(array(
|
||||
$session['es_id'],
|
||||
$uid,
|
||||
Helper::getRandomColor(),
|
||||
$uid,
|
||||
$memberColor,
|
||||
time()
|
||||
));
|
||||
|
||||
if ($member->insert()){
|
||||
// Do we have OC_Avatar in out disposal?
|
||||
if (!class_exists('\OC_Avatar') || \OC_Config::getValue('enable_avatars', true) !== true){
|
||||
//$x['avatar_url'] = \OCP\Util::linkToRoute('documents_user_avatar');
|
||||
$imageUrl = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAAAAACH5BAAAAAAALAAAAAABAAEAAAICTAEAOw==';
|
||||
} else {
|
||||
// https://github.com/owncloud/documents/issues/51
|
||||
// Temporary stub
|
||||
$imageUrl = $uid;
|
||||
|
||||
/*
|
||||
$avatar = new \OC_Avatar($uid);
|
||||
$image = $avatar->get(64);
|
||||
// User has an avatar
|
||||
if ($image instanceof \OC_Image) {
|
||||
$imageUrl = \OC_Helper::linkToRoute(
|
||||
'core_avatar_get',
|
||||
array( 'user' => $uid, 'size' => 64)
|
||||
) . '?requesttoken=' . \OC::$session->get('requesttoken');
|
||||
} else {
|
||||
//shortcircuit if it's not an image
|
||||
$imageUrl = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAAAAACH5BAAAAAAALAAAAAABAAEAAAICTAEAOw==';
|
||||
}
|
||||
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
$session['member_id'] = (string) $member->getLastInsertId();
|
||||
$op = new Db_Op();
|
||||
$op->addMember(
|
||||
$session['es_id'],
|
||||
$session['member_id'],
|
||||
\OCP\User::getDisplayName($uid),
|
||||
$memberColor,
|
||||
$imageUrl
|
||||
);
|
||||
} else {
|
||||
throw new \Exception('Failed to add member into database');
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user