Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions app/channels/asset_sync_channel.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# frozen_string_literal: true

class AssetSyncChannel < ApplicationCable::Channel
include Canaid::Helpers::PermissionsHelper

def subscribed
asset = Asset.find_by(id: params[:asset_id])

return reject unless asset&.file&.attached?
return reject unless can_manage_asset?(current_user, asset) && can_open_asset_locally?(current_user, asset)

stream_for asset

transmit({ checksum: asset.file.checksum })
end

def unsubscribed
stop_all_streams
end
end
2 changes: 2 additions & 0 deletions app/controllers/asset_sync_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ def update
log_activity(:edit)
end

AssetSyncChannel.broadcast_to(@asset, checksum: @asset.file.checksum)

if asset_conflicts
ActiveRecord::Base.transaction do
conflict_response = AssetSyncTokenSerializer.new(@asset_sync_token).as_json
Expand Down
4 changes: 0 additions & 4 deletions app/controllers/assets_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -442,10 +442,6 @@ def duplicate
end
end

def checksum
render json: { checksum: @asset.file.blob.checksum }
end

def versions
blobs =
[@asset.file.blob] +
Expand Down
1 change: 0 additions & 1 deletion app/controllers/global_constants_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ def load_global_constants
FILENAME_MAX_LENGTH: Constants::FILENAME_MAX_LENGTH,
FAST_STATUS_POLLING_INTERVAL: Constants::FAST_STATUS_POLLING_INTERVAL,
SLOW_STATUS_POLLING_INTERVAL: Constants::SLOW_STATUS_POLLING_INTERVAL,
ASSET_POLLING_INTERVAL: Constants::ASSET_POLLING_INTERVAL,
ASSET_SYNC_URL: Constants::ASSET_SYNC_URL,
GLOBAL_SEARCH_PREVIEW_LIMIT: Constants::GLOBAL_SEARCH_PREVIEW_LIMIT,
SEARCH_LIMIT: Constants::SEARCH_LIMIT,
Expand Down
20 changes: 0 additions & 20 deletions app/javascript/vue/protocol/step.vue
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,6 @@
@attachment:deleted="attachmentDeleted"
@attachment:update="updateAttachment"
@attachment:uploaded="loadAttachments"
@attachment:changed="reloadAttachment"
@attachments:order="changeAttachmentsOrder"
@attachment:moved="moveAttachment"
@attachments:viewMode="changeAttachmentsViewMode"
Expand Down Expand Up @@ -596,25 +595,6 @@
this.$emit('step:drag_enter', this.step.id);
}
},
reloadAttachment(attachmentId) {
const index = this.attachments.findIndex(attachment => attachment.id === attachmentId);
const attachmentUrl = this.attachments[index].attributes.urls.asset_show

axios.get(attachmentUrl)
.then((response) => {
const updatedAttachment = response.data.data;
const index = this.attachments.findIndex(attachment => attachment.id === attachmentId);

if (index !== -1) {
this.attachments[index] = updatedAttachment;
}
})
.catch((error) => {
console.error("Failed to reload attachment:", error);
});

this.showFileModal = false;
},
showStorageUsage() {
return (this.elements.length || this.attachments.length) && !this.isCollapsed && this.step.attributes.storage_limit;
},
Expand Down
3 changes: 1 addition & 2 deletions app/javascript/vue/shared/content/attachments.vue
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
<div class="attachments" :data-parent-id="parent.id">
<component
v-for="(attachment, index) in attachmentsOrdered"
:key="attachment.id"
:key="`${attachment.id}-${attachment.attributes.checksum}`"
:is="attachment_view_mode(attachmentsOrdered[index])"
:attachment="attachment"
:parentId="parseInt(parent.id)"
Expand All @@ -42,7 +42,6 @@
@attachment:archive="deleteAttachment(attachment.id)"
@attachment:moved="attachmentMoved"
@attachment:uploaded="$emit('attachment:uploaded')"
@attachment:changed="$emit('attachment:changed', $event)"
@attachment:update="$emit('attachment:update', $event)"
/>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@
@attachment:delete="$emit('attachment:delete', $event)"
@attachment:moved="$emit('attachment:moved', $event)"
@attachment:uploaded="$emit('attachment:uploaded', $event)"
@attachment:changed="$emit('attachment:changed', $event)"
@attachment:update="$emit('attachment:update', $event)"
@menu-toggle="$emit('attachment:toggle_menu', $event)"
@attachment:versionRestored="$emit('attachment:versionRestored', $event)"
Expand All @@ -72,7 +71,6 @@
</template>

<script>
import OpenLocallyMixin from './mixins/open_locally.js';
import OpenMenu from './open_menu.vue';
import ContextMenu from './context_menu.vue';
import deleteAttachmentModal from './delete_modal.vue';
Expand All @@ -92,7 +90,6 @@ export default {
default: ''
}
},
mixins: [OpenLocallyMixin],
data() {
return {
deleteModal: false,
Expand Down
6 changes: 1 addition & 5 deletions app/javascript/vue/shared/content/attachments/inline.vue
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@
@attachment:moved="attachmentMoved"
@attachment:uploaded="reloadAttachments"
@attachment:versionRestored="reloadAttachments"
@attachment:changed="$emit('attachment:changed', $event)"
@attachment:update="$emit('attachment:update', $event)"
@attachment:toggle_menu="toggleMenuDropdown"
@attachment:move_modal="showMoveModal"
Expand Down Expand Up @@ -110,19 +109,16 @@ import ContextMenu from './context_menu.vue';
import PdfViewer from '../../pdf_viewer.vue';
import MoveAssetModal from '../modal/move.vue';
import MoveMixin from './mixins/move.js';
import OpenLocallyMixin from './mixins/open_locally.js';
import AttachmentActions from './attachment_actions.vue';
import OpenMenu from './open_menu.vue';
import LockedTag from '../../snippets/locked_tag.vue';

export default {
name: 'inlineAttachment',
mixins: [ContextMenuMixin, AttachmentMovedMixin, MoveMixin, OpenLocallyMixin],
mixins: [ContextMenuMixin, AttachmentMovedMixin, MoveMixin],
components: {
ContextMenu,
PdfViewer,
MoveAssetModal,
OpenMenu,
AttachmentActions,
LockedTag
},
Expand Down
3 changes: 0 additions & 3 deletions app/javascript/vue/shared/content/attachments/list.vue
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@
@attachment:moved="attachmentMoved"
@attachment:uploaded="reloadAttachments"
@attachment:versionRestored="reloadAttachments"
@attachment:changed="$emit('attachment:changed', $event)"
@attachment:update="$emit('attachment:update', $event)"
@attachment:toggle_menu="toggleMenuDropdown"
@attachment:move_modal="showMoveModal"
Expand All @@ -79,7 +78,6 @@ import ContextMenu from './context_menu.vue';
import MoveMixin from './mixins/move.js';
import MoveAssetModal from '../modal/move.vue';
import AttachmentActions from './attachment_actions.vue';
import OpenMenu from './open_menu.vue';
import LockedTag from '../../snippets/locked_tag.vue';

export default {
Expand All @@ -88,7 +86,6 @@ export default {
components: {
ContextMenu,
MoveAssetModal,
OpenMenu,
AttachmentActions,
LockedTag
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ export default {
showNoPredefinedAppModal: false,
showRestrictedExtensionModal: false,
showUpdateVersionModal: false,
editAppModal: false,
pollingInterval: null
editAppModal: false
};
},
components: {
Expand All @@ -36,9 +35,6 @@ export default {
&& this.attributes.asset_type !== 'marvinjs';
}
},
beforeUnmount() {
this.stopPolling();
},
methods: {
async checkScinoteEditRunning() {
// responses will be cached on window, so the requests only run once per page load
Expand Down Expand Up @@ -119,7 +115,6 @@ export default {

this.editAppModal = true;
try {
this.startPolling();
const { data } = await axios.get(this.attributes.urls.open_locally);
await axios.post(`${this.attributes.urls.open_locally_api}/download`, data);
} catch (error) {
Expand All @@ -129,33 +124,6 @@ export default {
isWrongVersion(version) {
const { min, max } = this.attributes.edit_version_range;
return !satisfies(version, `${min} - ${max}`);
},
async pollForChanges() {
try {
const checksumResponse = await axios.get(this.attributes.urls.asset_checksum);

if (checksumResponse.status === 200) {
const currentChecksum = checksumResponse.data.checksum;

if (currentChecksum !== this.attributes.checksum) {
this.$emit('attachment:changed', this.attachment.id);
}
}
} catch (error) {
console.error('Error polling for changes:', error);
this.stopPolling();
}
},
startPolling() {
if (this.pollingInterval === null) {
this.pollingInterval = setInterval(this.pollForChanges, GLOBAL_CONSTANTS.ASSET_POLLING_INTERVAL);
}
},
stopPolling() {
if (this.pollingInterval !== null) {
clearInterval(this.pollingInterval);
this.pollingInterval = null;
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@
</template>

<script>
import { markRaw } from 'vue';
import consumer from '../../../../channels/consumer';
import OpenLocallyMixin from './mixins/open_locally.js';
import MenuDropdown from '../../menu_dropdown.vue';
import UpdateVersionModal from '../modal/update_version_modal.vue';
Expand All @@ -77,14 +79,19 @@ export default {
},
data() {
return {
fileVersionsModal: false
fileVersionsModal: false,
fileChangesSubscription: null
};
},
created() {
this.fetchLocalAppInfo();
window.openLocallyMenu = this;
},
mounted() {
this.subscribeFileChanges();
},
beforeUnmount() {
this.unsubscribeFileChanges();
delete window.openLocallyMenuComponent;
},
computed: {
Expand Down Expand Up @@ -133,6 +140,28 @@ export default {
openImageEditor() {
document.getElementById('editImageButton').click();
},
subscribeFileChanges() {
if (this.fileChangesSubscription || !this.attachment.attributes.urls.open_locally) return;

// markRaw, because ActionCable forgets a subscription by identity and would
// never match a reactive proxy of it - so unsubscribing would silently no-op.
this.fileChangesSubscription = markRaw(consumer.subscriptions.create(
{ channel: 'AssetSyncChannel', asset_id: this.attachment.attributes.id },
{
received: (data) => {
if (data.checksum === this.attachment.attributes.checksum) return;
this.refreshPreview();
},
rejected: () => this.unsubscribeFileChanges()
}
));
},
unsubscribeFileChanges() {
if (!this.fileChangesSubscription) return;

consumer.subscriptions.remove(this.fileChangesSubscription);
this.fileChangesSubscription = null;
},
refreshPreview() {
const filePreview = document.querySelector('.file-preview-container');

Expand Down
3 changes: 0 additions & 3 deletions app/javascript/vue/shared/content/attachments/thumbnail.vue
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@
@attachment:moved="attachmentMoved"
@attachment:uploaded="reloadAttachments"
@attachment:versionRestored="reloadAttachments"
@attachment:changed="$emit('attachment:changed', $event)"
@attachment:update="$emit('attachment:update', $event)"
@attachment:toggle_menu="toggleMenu"
@attachment:move_modal="showMoveModal"
Expand Down Expand Up @@ -119,7 +118,6 @@ import MenuDropdown from '../../../shared/menu_dropdown.vue';
import MoveAssetModal from '../modal/move.vue';
import MoveMixin from './mixins/move.js';
import PreviewStatusMixin from './mixins/preview_status.js';
import OpenMenu from './open_menu.vue';
import AttachmentActions from './attachment_actions.vue';
import { vOnClickOutside } from '@vueuse/components';
import LockedTag from '../../snippets/locked_tag.vue';
Expand All @@ -132,7 +130,6 @@ export default {
deleteAttachmentModal,
MoveAssetModal,
MenuDropdown,
OpenMenu,
AttachmentActions,
LockedTag
},
Expand Down
Loading