Ionic - iPhone X statusbar overlays shared header component - ios

I have seen various similar posts with the problem of the iOS status bar overlaying onto the header of apps.
I haven’t yet seen another post which has the same problem as mine.
I am trying to use a shared header component for certain pages and when I use this, I get the overlaying problem.
I have simplified the code and recreated my problem using the ionic tabs starter template:
This page is using a shared header component:
<ion-header>
<shared-header title="Home - shared header"></shared-header>
</ion-header>
shared-header.component.html
<ion-navbar>
<ion-title>{{title}}</ion-title>
</ion-navbar>
shared-header.component.ts
import { Component, Input } from '#angular/core';
#Component({
selector: 'shared-header',
templateUrl: 'shared-header.component.html'
})
export class SharedHeaderComponent {
#Input('title') title: string;
constructor() { }
}
This page is not using the shared header component:
<ion-header>
<ion-navbar>
<ion-title>
About
</ion-title>
</ion-navbar>
</ion-header>
Why would this be happening? Is it because of the extra <shared-header></shared-header> tags? If so, what can be done to solve this?

The problem is caused by having the component tag inside the header tag, for some reason this causes the header to render incorrectly. The solution I used was to use an attribute in the header instead of the component tags.
Inside the component wrap the selector in square brackets to define it be able to use it as an attribute
shared-header.component.ts
import { Component, Input } from '#angular/core';
#Component({
selector: '[shared-header]',
templateUrl: 'shared-header.component.html'
})
export class SharedHeaderComponent {
#Input('title') title: string;
constructor() { }
}
then in the header you can inject the component as an attribute like this
<ion-header shared-header title="Home - shared header">
</ion-header>
If you want to have access to your component via tags as well as an attribute, you can define multiple selectors
#Component({
selector:'[shared-header], shared-header',
templateUrl: 'shared-header.component.html'
})

You can try these below steps
1) Using statusbar cordova plugin, you can set
if (this.statusBar) {
this.statusBar.styleDefault();
this.statusBar.overlaysWebView(false);
}
2) In index.html, meta tag include 'viewport-fit=cover'
<meta name="viewport" content="viewport-fit=cover, width=device-width, initial-scale=1.0, maximum-scale=1.0, target-densityDpi=device-dpi"/>
Can you also try adding padding-top to the header classes
header {
/* ... */
/* Status bar height on iOS 10 */
padding-top: 0px;
/* Status bar height on iOS 11.0 */
padding-top: constant(safe-area-inset-top);
/* Status bar height on iOS 11+ */
padding-top: env(safe-area-inset-top);
}

Related

Behavior is wrong when adding multiple Tab components to TaskCanvasTabs in Twilio Flex

I am developing a Twilio Flex plugin using Flex Ui version 2 (beta.1 and beta.2).
I wanted to add multiple tabs to TaskCanvasTabs and tried to write the following code.
import React from 'react';
import { Tab } from '#twilio/flex-ui';
import { FlexPlugin } from '#twilio/flex-plugin';
import SmsPanel from './components/SmsPanel/SmsPanel';
import IncomingVideo from './components/IncomingVideo/IncomingVideo';
const PLUGIN_NAME = 'SendSmsV2Plugin';
export default class SendSmsV2Plugin extends FlexPlugin {
constructor() {
super(PLUGIN_NAME);
}
/**
* This code is run when your plugin is being started
* Use this to modify any UI components or attach to the actions framework
*
* #param flex { typeof import('#twilio/flex-ui') }
*/
async init(flex, manager) {
const options = {
align: 'end',
};
flex.TaskCanvasTabs.Content.add(
<Tab label='SMS' key='sms-panel-tab-key'>
<SmsPanel key='sms-panel-component' />
</Tab>,
options,
);
flex.TaskCanvasTabs.Content.add(
<Tab label='Video' key='video-panel-tab-key'>
<IncomingVideo key='incoming-video-component' />
</Tab>,
options,
);
}
}
When executed, the first Tab (SMS) added will be duplicated as shown below. Thereafter, each time I select the first Tab, Call tab, etc., the first Tab added will be increased.
Can someone please tell me if the specification does not allow adding multiple tabs to TaskCanvasTabs or how to solve this problem?
I also tried with Flex Ui version 2 (beta.3) but the behavior is the same.
It seems that this issue only happens when you try to add multiple tabs on TaskCanvasTabs
To resolve this issue you could add a Tab Group which contains Tabs
flex.TaskCanvasTabs.Content.add(
<Flex.Tabs key="custom-tabs-group">
<Flex.Tab key="conversation-note-tab" label="Conversation Notes">
<ConversationNote key="conversation-note" />
</Flex.Tab>
<Flex.Tab key="label-to-conversation" label="Conversation Label">
<AttachLabelToConversation key="add-label-to-conversation" />
</Flex.Tab>
</Flex.Tabs>,
{}
);
Use this css to adjust the tab group text
/* Added CSS for merged TaskCanvasTabs into Tabs group start */
.Twilio-TaskCanvas .Twilio-TaskCanvas-default .Twilio-TaskCanvasTabs div[data-test="customer-tab-header"]:has(> div > button) button {
width: 100%;
height: 100%;
}
.Twilio-TaskCanvas .Twilio-TaskCanvas-default .Twilio-TaskCanvasTabs div[data-test="customer-tab-header"]:has(> div > button) button:hover {
background-color: unset;
}
.Twilio-TaskCanvas .Twilio-TaskCanvas-default .Twilio-TaskCanvasTabs div[data-test="customer-tab-header"]:has(> div > button) button div svg {
display: none;
}
.Twilio-TaskCanvas .Twilio-TaskCanvas-default .Twilio-TaskCanvasTabs div[data-test="customer-tab-header"]:has(> div > button) button div:after {
content: "Conversation Actions";
font-size: 14px;
font-weight: 600;
color: rgb(96, 107, 133);
padding-bottom: 6px;
}
/* Added CSS for merged TaskCanvasTabs into Tabs group end */
I heard the best solution.
TabPros is using the optional uniqueName prop instead of the key for identifying the selected tab.
So, I changed my code below. It was fixed.
flex.TaskCanvasTabs.Content.add(
<Tab label='SMS' key='sms-panel-tab-key' uniqueName='sms-panel-tab'>
<SmsPanel key='sms-panel-component' />
</Tab>,
options,
);
flex.TaskCanvasTabs.Content.add(
<Tab label='Video' key='video-panel-tab-key' uniqueName='video-panel-tab'>
<IncomingVideo key='incoming-video-component' />
</Tab>,
options,
);
The link referenced is below.
https://github.com/twilio/flex-plugin-builder/issues/327

react-native-webview scalesPageToFit - ios

In Webview props I set the scalesPageToFit prop to false.
In android OS I get nice and good view of the webview.
but on IOS I get small view of the webview as shown in desktop, because this prop is not supported in IOS.
I tried to add the property contentMode={'mobile'} but no change.
is there any other prop that might do the job or is there anything else that could help?
Environment:
OS: Ios
OS version: *
react-native version: 0.63.4
react-native-webview version: 10.9.2, 11.0.0
I used injectedJavaScriptBeforeContentLoaded as prop of the webview and injected meta label to the head tag of the html.
this is the code I injected
setTimeout(function () {
var met = document.createElement('meta');
met.content = 'width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1';
met.charset = 'UTF-8';
met.name = 'viewport';
var head = document.getElementsByTagName("head")[0];
head.append(met);
}, 500)
Uri's example worked and as I dug into this more to find out why I simplified the solution for my project. I had control of the html the device was trying to show so I changed the meta tag to:
<meta name="viewport" content="width=device-width, initial-scale=1.0">
I found this on w3 schools article on viewports https://www.w3schools.com/css/css_rwd_viewport.asp
You could use Uri's meta code to insert the above if needed.
Here's what worked for me:
My webview:
<View style={styles.viewWrapper}>
<WebView onNavigationStateChange={this.onNavigationStateChange} ref=.
{this.WEBVIEW_REF} style={styles.webviewStyle} source={{ uri:
this.state.link }} />
</View>
My styles:
import {
Dimensions
} from 'react-native';
const deviceHieght = Dimensions.get('window').height;
const webViewHieght = deviceHieght-80;
viewWrapper: {
height: webViewHieght
},
webviewStyle: {
width: '100%',
height: 50000,
flex: 1
},
The reason why I'm subtracting 80 from deviceHeight is because of the size of my header. I've set the height of my webviewStyle very high because I have a long webpage that I want people to be able to scroll down. The page this webview is in has an outer view with a flex of 1.
So basically, for your needs I would just modify this to be whatever height and width you want.

Mat-select panel min-width

I'm trying to customize mat-select with multiple checkboxes.
for some reason the panel get wrong min-width as below:
and I don't know where its calculating this min-width.
also I tried to add panelClass and override the min-width from this class,
for example:
<mat-select #multipleSelect (selectionChange)="selectItem($event.value)" panelClass="multiple-panel" multiple>
&.multiple-panel {
min-width: 200px !important;
}
but when opening the dropdown its open with the original width (like in the pic) and after few millisecond"jump" to the custom min-width defined on the panel class.
I find the mat-select very hard to style. anybody knows how to solve this problem?
You can style your mat-select dialog box by giving a panel class (as you mentioned).
Please follow this demo : https://stackblitz.com/edit/angular-matselect-style?file=src/styles.css
to see the styled mat-select components.
Reason :
Reason for the delay is that angular for dialog-boxes, create a cdk-overlay-pane inside the cdk-overlay-container container, So in case of mat-select it provides a min-width of 180px, which is overridden by our panel class in the slight delay.
Yes, there is a slight delay in opening of dialog box and customizing its width to the specified width provided in the panel class. But the delay is acceptable in the project that i was working on. So, you can find the demo for styling the mat-select component, as i have provided 2 components and you can modify any css properties.
Try to use styles using ::ng-deep or :host >>>, if not finding any luck, please paste the styles in style.css.
Update 1 :
Tried css animations, and opacity for making smooth opening of the mat-select options.
.panel-class-applied-on-mat-select {
animation-name: opacityDelay !important;
animation-duration: 0.3s !important;
}
#keyframes opacityDelay {
0% {opacity: 0;}
25% {opacity: 0;}
50% {opacity: 0;}
75% {opacity: 0;}
100% {opacity: 1;}
}
Updated StackBlitz Demo
I used another approach.
Just added this piece of code to global style.
.mat-select-panel {
// some your code
&.ng-animating {
visibility: hidden;
}
}
You can try this solution on
DEMO StackBlitz.
Hack with opacity did not fix jumping width when select is closing.
You'll need to change viewEncapsulation to none at your component decorator.and then add following css to remove the transition effect.Have a look at viewencapsulation in angular docs https://angular.io/guide/component-styles#view-encapsulation.
#Component({
selector: 'app-selector',
templateUrl: './template.html',
styleUrls: ['./template.css'],
encapsulation: ViewEncapsulation.None
})
//CSS
.cdk-overlay-connected-position-bounding-box .cdk-overlay-pane .mat-select-panel.ng-animating {
display: none;
}
Try this way : define a panel class for your mat-select in the code and then in the global/app styling file just add:
.panel-class-name .mat-select-panel {
// add your styling here
}
It worked for me to add some component specific styling for material components.
Please go easy on me S.O. This is my first time contributing. :)
After debugging the console, and running into this issue. Solutions were not clear online. So I'm posting mine here in case someone else runs into this.
I found that there is a width permanently set for the infix class. If you unset it, and optionally add some padding to the right of the value, you'll find that will resolve the issue. Add :host for encapsulation when using ::ng-deep.
Important to Note: ::ng-deep is being permanently deprecated after Angular v14.
There is a property in the #Component() annotation called encapsulation which can be used to turn off the view encapsulation for the component instead of using ::ng-deep.
Solution for the deprecation of ::ng-deep:
#Component({
selector: 'app-selector-name',
template: `<div>Hello World!</div>`,
encapsulation: ViewEncapsulation.None,
styles: [
`
:host mat-form-field .mat-form-field-infix {
width: unset;
}
:host mat-form-field .mat-select-value {
padding-right: 0.5rem; /* 8px */
/* Alternatively, for TailwindCSS: #apply pr-2 */
}
:host .random-class {
/* some encapsulated styling... */
}
.another-random-class {
/* some non-encapsulated styling... */
}
`
]
})
Solution if you do not care about the deprecation of ::ng-deep:
:host ::ng-deep mat-form-field .mat-form-field-infix {
width: unset;
}
:host ::ng-deep mat-form-field .mat-select-value {
padding-right: 0.5rem; /* 8px */
}

How to add a placeholder in CKEditor 5?

import BalloonEditor from '#ckeditor/ckeditor5-editor-balloon/src/ballooneditor';
import Essentials from '#ckeditor/ckeditor5-essentials/src/essentials';
import Paragraph from '#ckeditor/ckeditor5-paragraph/src/paragraph';
import Bold from '#ckeditor/ckeditor5-basic-styles/src/bold';
import Italic from '#ckeditor/ckeditor5-basic-styles/src/italic';
BalloonEditor
.create( elem, {
plugins: [ Markdown, Essentials, Paragraph, Bold, Italic ],
toolbar: [ 'bold' ]
})
.then((editor) => {
....
})
.catch( error => {
console.error( error );
} );
I tried to use attachPlaceholder from https://ckeditor.com/docs/ckeditor5/latest/api/module_engine_view_placeholder.html#static-function-attachPlaceholder
import { attachPlaceholder } from "#ckeditor/ckeditor5-engine/src/view/placeholder";
Could you show me simple example how to use this method (attachPlaceholder) or how to do it.
In CKEditor-5 you can add placeholder like
<ckeditor [config]="{ placeholder:'Placeholder Text', toolbar: [ 'bold', 'italic', 'bulletedList' ] }">
</ckeditor>
See docs
I assume that you want to add a placeholder to the entire editor, so that when it's empty you can display something like "Type here...".
Unfortunately, the attachPlaceholder() function doesn't yet support setting placeholder for the editor's main editable. For now, it's used in cases like image captions:
There's a ticket to implement configurable editor's placeholders: https://github.com/ckeditor/ckeditor5/issues/479.
And there's a 3rd party addon which adds a placeholder in a simpler way: https://github.com/alexeckermann/ckeditor5-emptyness.
Plugin URL : https://github.com/alexeckermann/ckeditor5-emptyness
Simply build your editor with this plugin and you will get access to a isEmpty observable attribute (care of Observable) on your editor instance. Additionaly, the plugin will add a ck-editor__is-empty class name on the editor element when is is empty.
The origin use case was for the application to observe the attribute and know when the editor enters or exits an empty state. From there the application applies an attribute to the editors HTML element so that a CSS based placeholder can be applied — using CSS's ::before rules to inject phantom content without disturbing CKEditor's actual content.
import BalloonEditorBase from '#ckeditor/ckeditor5-editor-
balloon/src/ballooneditor';
import Emptyness from 'ckeditor5-emptyness/src/emptyness';
// .. all your other imports here
export default class MyEditor extends BalloonEditorBase { }
MyEditor.build = {
// ... all your other configs here
plugins: [
// ... all your other plugins here
Emptyness
]
};
CSS
.ck-editor__is-empty .ck-content.ck-editor__editable::before,
.ck-editor__is-empty.ck-content.ck-editor__editable::before {
content: 'The editor is empty';
position: absolute;
display: block;
margin: var(--ck-spacing-large) 0;
color: #aaa;
}

Using drag and drop in phonegap installed

I'm using simple HTML code to work on a drag and drop function as part of my IOS app. This piece of code works perfectly in the browser however when I copy it into my xcode file the image won't drag.
<!DOCTYPE HTML>
<html>
<head>
<style type="text/css">
#div1 {width:350px;height:70px;padding:10px;border:1px solid #aaaaaa;}
</style>
<script>
function allowDrop(ev)
{
ev.preventDefault();
}
function drag(ev)
{
ev.dataTransfer.setData("Text",ev.target.id);
}
function drop(ev)
{
ev.preventDefault();
var data=ev.dataTransfer.getData("Text");
ev.target.appendChild(document.getElementById(data));
}
</script>
</head>
<body>
<p>Drag the image into the rectangle:</p>
<div id="div1" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<br>
<img id="drag1" src="images/face.png" draggable="true" ondragstart="drag(event)" width="336" height="69">
</body>
</html>
Reading over Apple's webview capabilities document states that you have to set a CSS property for this to work.
From the docs:
Making an Element Draggable
WebKit provides automatic support to let users drag common items, such as images, links
and selected text. You can extend this support to include specific elements on an HTML
page. For example, you could mark a particular div or span tag as draggable.
To mark an arbitrary element as draggable, add the -webkit-user-drag attribute
(previously -khtml-user-drag) to the style definition of the element. Because it is a
cascading style sheet (CSS) attribute, you can include it as part of a style definition
or as an inline style attribute on the element tag. The values for this attribute are
listed in Table 1.
So standard draggables will work out of the box, but other elements like div or span require the -webkit-user-drag attribute to be appended.
Example:
#drag1 { -webkit-user-drag: element; }
Source: https://developer.apple.com/library/mac/documentation/AppleApplications/Conceptual/SafariJSProgTopics/Tasks/DragAndDrop.html
This code is what worked in the end.
<script>
var nodeList = document.getElementsByClassName('contents');
for(var i=0;i<nodeList.length;i++) {
var obj = nodeList[i];
obj.addEventListener('touchmove', function(event) {
var touch = event.targetTouches[0];
// Place element where the finger is
event.target.style.left = touch.pageX + 'px';
event.target.style.top = touch.pageY + 'px';
event.preventDefault();
});
}
</script>

Resources