1/*
2 * Copyright 2020, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17export default {
18  name: 'FocusedDataViewFinder',
19  created() {
20    document.addEventListener('scroll', this.updateFocusedView);
21  },
22  deleted() {
23    document.removeEventListener('scroll', this.updateFocusedView);
24  },
25  computed: {
26    timelineFiles() {
27      return this.$store.getters.timelineFiles;
28    },
29  },
30  methods: {
31    updateFocusedView() {
32      const positions = this.getDataViewPositions();
33      const focusedFile = this.findFocusedDataView(positions);
34
35      this.$store.commit('setFocusedFile', focusedFile);
36    },
37    getDataViewPositions() {
38      const positions = {};
39
40      for (const file of this.files) {
41        const dataView = this.$refs[file.type];
42        if (!dataView || dataView.length === 0) {
43          continue;
44        }
45
46        const dataViewEl = dataView[0].$el;
47        positions[file.type] = dataViewEl.getBoundingClientRect();
48      }
49
50      return positions;
51    },
52    /**
53     * Returns the file of the DataView that takes up the most of the visible
54     * screen space.
55     * @param {Object} positions A map from filenames to their respective
56     *                           boundingClientRect.
57     * @return {String} The dataView that is in focus.
58     */
59    findFocusedDataView(positions) {
60      const visibleHeight =
61        Math.max(document.documentElement.clientHeight || 0,
62            window.innerHeight || 0);
63
64      let maxScreenSpace = 0;
65      let focusedDataView = this.files[0];
66      for (const file of this.files) {
67        const pos = positions[file.type];
68        if (!pos) {
69          continue;
70        }
71
72        let screenSpace = 0;
73        if (0 <= pos.top && pos.top <= visibleHeight) {
74          screenSpace = Math.min(visibleHeight, pos.bottom) - pos.top;
75        } else if (0 <= pos.bottom && pos.bottom <= visibleHeight) {
76          screenSpace = pos.bottom - Math.max(0, pos.top);
77        } else if (pos.top <= 0 && pos.bottom >= visibleHeight) {
78          screenSpace = visibleHeight;
79        }
80
81        if (screenSpace >= maxScreenSpace) {
82          maxScreenSpace = screenSpace;
83          focusedDataView = file;
84        }
85      }
86
87      return focusedDataView;
88    },
89  },
90};
91