task.tsx 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. /**
  2. * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author David Sehnal <david.sehnal@gmail.com>
  5. */
  6. import { PluginReactContext, PluginUIComponent } from './base';
  7. import { OrderedMap } from 'immutable';
  8. import { TaskManager } from '../mol-plugin/util/task-manager';
  9. import { Progress } from '../mol-task';
  10. import { IconButton } from './controls/common';
  11. import { CancelSvg } from './controls/icons';
  12. import { useContext, useEffect, useState } from 'react';
  13. import { useBehavior } from './hooks/use-behavior';
  14. export function BackgroundTaskProgress() {
  15. const plugin = useContext(PluginReactContext);
  16. const [tracked, setTracked] = useState<OrderedMap<number, TaskManager.ProgressEvent>>(OrderedMap());
  17. useEffect(() => {
  18. const started = plugin.events.task.progress.subscribe(e => {
  19. const hideOverlay = !!plugin.spec.components?.hideTaskOverlay;
  20. if (e.level === 'background' && (hideOverlay || !e.useOverlay)) {
  21. setTracked(tracked => tracked.set(e.id, e));
  22. }
  23. });
  24. const finished = plugin.events.task.finished.subscribe(({ id }) => {
  25. setTracked(tracked => tracked.delete(id));
  26. });
  27. return () => {
  28. started.unsubscribe();
  29. finished.unsubscribe();
  30. };
  31. }, [plugin]);
  32. return <div className='msp-background-tasks'>
  33. {tracked.valueSeq().map(e => <ProgressEntry key={e!.id} event={e!} />)}
  34. <CanvasCommitState />
  35. </div>;
  36. }
  37. function CanvasCommitState() {
  38. const plugin = useContext(PluginReactContext);
  39. const queueSize = useBehavior(plugin.canvas3d?.commitQueueSize);
  40. if (!queueSize) return null;
  41. return <div className='msp-task-state'>
  42. <div>
  43. <div>
  44. Commiting renderables... {queueSize} remaining
  45. </div>
  46. </div>
  47. </div>;
  48. }
  49. class ProgressEntry extends PluginUIComponent<{ event: TaskManager.ProgressEvent }> {
  50. abort = () => {
  51. this.plugin.managers.task.requestAbort(this.props.event.progress.root.progress.taskId, 'User Request');
  52. };
  53. render() {
  54. const root = this.props.event.progress.root;
  55. const subtaskCount = countSubtasks(this.props.event.progress.root) - 1;
  56. const pr = root.progress.isIndeterminate
  57. ? void 0
  58. : <>[{root.progress.current}/{root.progress.max}]</>;
  59. const subtasks = subtaskCount > 0
  60. ? <>[{subtaskCount} subtask(s)]</>
  61. : void 0;
  62. return <div className='msp-task-state'>
  63. <div>
  64. {root.progress.canAbort && <IconButton svg={CancelSvg} onClick={this.abort} title='Abort' />}
  65. <div>
  66. {root.progress.message} {pr} {subtasks}
  67. </div>
  68. </div>
  69. </div>;
  70. }
  71. }
  72. function countSubtasks(progress: Progress.Node) {
  73. if (progress.children.length === 0) return 1;
  74. let sum = 0;
  75. for (const c of progress.children) sum += countSubtasks(c);
  76. return sum;
  77. }
  78. export function OverlayTaskProgress() {
  79. const plugin = useContext(PluginReactContext);
  80. const [tracked, setTracked] = useState<OrderedMap<number, TaskManager.ProgressEvent>>(OrderedMap());
  81. useEffect(() => {
  82. const started = plugin.events.task.progress.subscribe(e => {
  83. if (!!e.useOverlay) {
  84. setTracked(tracked => tracked.set(e.id, e));
  85. }
  86. });
  87. const finished = plugin.events.task.finished.subscribe(({ id }) => {
  88. setTracked(tracked => tracked.delete(id));
  89. });
  90. return () => {
  91. started.unsubscribe();
  92. finished.unsubscribe();
  93. };
  94. }, [plugin]);
  95. if (tracked.size === 0) return null;
  96. return <div className='msp-overlay-tasks'>
  97. {tracked.valueSeq().map(e => <ProgressEntry key={e!.id} event={e!} />)}
  98. </div>;
  99. }