Skip to content

Commit fcf18cc

Browse files
author
dessant
committed
fix: handle list overflowing on small screens
1 parent 56955c5 commit fcf18cc

File tree

4 files changed

+267
-35
lines changed

4 files changed

+267
-35
lines changed

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
"lodash": "^4.17.4",
3939
"storage-versions": "dessant/storage-versions#^0.1.1",
4040
"vue": "^2.5.13",
41+
"vue-resize": "^0.4.3",
4142
"vuedraggable": "^2.15.0",
4243
"webextension-polyfill": "^0.2.1"
4344
},
@@ -48,6 +49,7 @@
4849
"babel-plugin-lodash": "^3.3.2",
4950
"babel-preset-env": "^1.6.1",
5051
"babel-preset-minify": "^0.2.0",
52+
"babel-preset-stage-0": "^6.24.1",
5153
"css-loader": "^0.28.7",
5254
"cssnano": "^3.10.0",
5355
"del": "^3.0.0",

src/action/App.vue

Lines changed: 107 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@
1313
</div>
1414
</div>
1515

16-
<transition name="settings">
16+
<transition name="settings"
17+
@before-enter="beforeSettingsEnter"
18+
@after-enter="afterSettingsEnter"
19+
@after-leave="afterSettingsLeave">
1720
<div class="settings" v-show="showSettings">
1821
<v-textfield v-model="customUrl"
1922
:placeholder="getText('inputPlaceholder_customURL')"
@@ -22,33 +25,39 @@
2225
</div>
2326
</transition>
2427

25-
<ul class="mdc-list list">
26-
<li class="mdc-list-item item ripple-surface"
27-
v-if="searchAllEngines"
28+
<div class="list-padding-top"></div>
29+
<ul class="mdc-list list list-bulk-button" v-if="searchAllEngines">
30+
<li class="mdc-list-item list-item ripple-surface"
2831
@click="selectEngine('allEngines')">
29-
<img class="mdc-list-item__start-detail item-icon"
32+
<img class="mdc-list-item__start-detail list-item-icon"
3033
:src="getIcon('allEngines')">
3134
{{ getText('engineName_allEngines_full') }}
3235
</li>
33-
<li role="separator" class="mdc-list-divider"
34-
v-if="searchAllEngines || engines.length > 8">
35-
</li>
36-
<div class="items">
37-
<li class="mdc-list-item item ripple-surface"
36+
</ul>
37+
<ul class="mdc-list list list-separator"
38+
v-if="searchAllEngines || hasScrollBar">
39+
<li role="separator" class="mdc-list-divider"></li>
40+
</ul>
41+
<div class="list-items-wrap" ref="items" :class="listClasses">
42+
<resize-observer @notify="handleSizeChange"></resize-observer>
43+
<ul class="mdc-list list list-items">
44+
<li class="mdc-list-item list-item ripple-surface"
3845
v-for="engine in engines"
3946
:key="engine.id"
4047
@click="selectEngine(engine)">
41-
<img class="mdc-list-item__start-detail item-icon"
48+
<img class="mdc-list-item__start-detail list-item-icon"
4249
:src="getIcon(engine)">
4350
{{ getText(`engineName_${engine}_short`) }}
4451
</li>
45-
</div>
46-
</ul>
52+
</ul>
53+
</div>
54+
4755
</div>
4856
</template>
4957

5058
<script>
5159
import browser from 'webextension-polyfill';
60+
import {ResizeObserver} from 'vue-resize';
5261
import {TextField} from 'ext-components';
5362
5463
import storage from 'storage/storage';
@@ -63,21 +72,34 @@ import {targetEnv} from 'utils/config';
6372
6473
export default {
6574
components: {
66-
[TextField.name]: TextField
75+
[TextField.name]: TextField,
76+
[ResizeObserver.name]: ResizeObserver
6777
},
6878
6979
data: function() {
7080
return {
7181
dataLoaded: false,
7282
7383
showSettings: false,
84+
hasScrollBar: false,
85+
hideScrollBar: false,
86+
isAndroid: false,
7487
7588
engines: [],
7689
searchAllEngines: false,
7790
customUrl: ''
7891
};
7992
},
8093
94+
computed: {
95+
listClasses: function() {
96+
return {
97+
'list-items-scroll-bar-hidden': this.hideScrollBar,
98+
'list-items-max-height': !this.isAndroid
99+
};
100+
}
101+
},
102+
81103
methods: {
82104
getText: getText,
83105
@@ -117,6 +139,24 @@ export default {
117139
} else {
118140
window.close();
119141
}
142+
},
143+
144+
handleSizeChange: function() {
145+
const items = this.$refs.items;
146+
this.hasScrollBar = items.scrollHeight > items.clientHeight;
147+
},
148+
149+
beforeSettingsEnter: function() {
150+
this.hideScrollBar = !this.hasScrollBar;
151+
},
152+
153+
afterSettingsEnter: function() {
154+
this.handleSizeChange();
155+
this.hideScrollBar = false;
156+
},
157+
158+
afterSettingsLeave: function() {
159+
this.handleSizeChange();
120160
}
121161
},
122162
@@ -127,14 +167,13 @@ export default {
127167
);
128168
const enEngines = await getEnabledEngines(options);
129169
130-
if (
131-
targetEnv === 'firefox' &&
132-
(await isAndroid()) &&
133-
(enEngines.length <= 1 || options.searchAllEnginesAction === 'main')
134-
) {
135-
// Removing the action popup has no effect on Android
136-
showNotification({messageId: 'error_optionsNotApplied'});
137-
return;
170+
if (targetEnv === 'firefox' && (await isAndroid())) {
171+
this.isAndroid = true;
172+
if (enEngines.length <= 1 || options.searchAllEnginesAction === 'main') {
173+
// Removing the action popup has no effect on Android
174+
showNotification({messageId: 'error_optionsNotApplied'});
175+
return;
176+
}
138177
}
139178
140179
this.searchAllEngines = options.searchAllEnginesAction === 'sub';
@@ -143,11 +182,11 @@ export default {
143182
this.dataLoaded = true;
144183
145184
const mq = window.matchMedia('(min-width: 413px)');
146-
const widthChange = function(mq) {
185+
const mqChange = function(mq) {
147186
document.body.style.minWidth = mq.matches ? '413px' : 'initial';
148187
};
149-
mq.addListener(widthChange);
150-
widthChange(mq);
188+
mq.addListener(mqChange);
189+
mqChange(mq);
151190
}
152191
};
153192
</script>
@@ -160,6 +199,19 @@ $mdc-theme-primary: #1abc9c;
160199
@import '@material/typography/mixins';
161200
@import "@material/ripple/mixins";
162201
202+
@import 'vue-resize/dist/vue-resize';
203+
204+
html,
205+
body,
206+
#app {
207+
height: 100%;
208+
}
209+
210+
#app {
211+
display: flex;
212+
flex-direction: column;
213+
}
214+
163215
body {
164216
margin: 0;
165217
min-width: 413px;
@@ -222,23 +274,46 @@ body {
222274
opacity: 0;
223275
}
224276
225-
.items {
226-
max-height: 392px;
277+
.list {
278+
padding: 0 !important;
279+
}
280+
281+
.list-padding-top {
282+
margin-bottom: 8px;
283+
}
284+
285+
.list-bulk-button {
286+
height: 48px;
287+
}
288+
289+
.list-separator {
290+
height: 1px;
291+
}
292+
293+
.list-items-wrap {
227294
overflow-y: auto;
295+
position: relative;
228296
}
229297
230-
.list {
231-
padding-left: 0 !important;
232-
padding-right: 0 !important;
298+
.list-items-max-height {
299+
max-height: 392px;
300+
}
301+
302+
.list-items-scroll-bar-hidden {
303+
overflow-y: hidden;
304+
}
305+
306+
.list-items {
307+
padding-bottom: 8px !important;
233308
}
234309
235-
.item {
310+
.list-item {
236311
padding-left: 16px;
237312
padding-right: 48px;
238313
cursor: pointer;
239314
}
240315
241-
.item-icon {
316+
.list-item-icon {
242317
margin-right: 16px !important;
243318
}
244319

src/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
],
2727

2828
"content_security_policy":
29-
"default-src 'self'; img-src 'self' data:; connect-src *; object-src 'none'; child-src 'none'; form-action 'none';",
29+
"default-src 'self'; img-src 'self' data:; style-src 'self' 'unsafe-inline'; connect-src *; object-src 'none'; child-src 'none'; form-action 'none';",
3030

3131
"icons": {
3232
"16": "src/icons/app/icon-16.png",

0 commit comments

Comments
 (0)