bauiv1lib.purchase

UI related to purchasing items.

  1# Released under the MIT License. See LICENSE for details.
  2#
  3"""UI related to purchasing items."""
  4
  5from __future__ import annotations
  6
  7from typing import TYPE_CHECKING
  8
  9import bauiv1 as bui
 10
 11if TYPE_CHECKING:
 12    from typing import Any
 13
 14
 15class PurchaseWindow(bui.Window):
 16    """Window for purchasing one or more items."""
 17
 18    def __init__(
 19        self,
 20        items: list[str],
 21        transition: str = 'in_right',
 22        header_text: bui.Lstr | None = None,
 23    ):
 24        from bauiv1lib.store.item import instantiate_store_item_display
 25
 26        plus = bui.app.plus
 27        assert plus is not None
 28
 29        assert bui.app.classic is not None
 30        store = bui.app.classic.store
 31
 32        if header_text is None:
 33            header_text = bui.Lstr(
 34                resource='unlockThisText',
 35                fallback_resource='unlockThisInTheStoreText',
 36            )
 37        if len(items) != 1:
 38            raise ValueError('expected exactly 1 item')
 39        self._items = list(items)
 40        self._width = 580
 41        self._height = 520
 42        uiscale = bui.app.ui_v1.uiscale
 43        super().__init__(
 44            root_widget=bui.containerwidget(
 45                size=(self._width, self._height),
 46                transition=transition,
 47                toolbar_visibility='menu_currency',
 48                scale=(
 49                    1.2
 50                    if uiscale is bui.UIScale.SMALL
 51                    else 1.1
 52                    if uiscale is bui.UIScale.MEDIUM
 53                    else 1.0
 54                ),
 55                stack_offset=(0, -15)
 56                if uiscale is bui.UIScale.SMALL
 57                else (0, 0),
 58            )
 59        )
 60        self._is_double = False
 61        self._title_text = bui.textwidget(
 62            parent=self._root_widget,
 63            position=(self._width * 0.5, self._height - 30),
 64            size=(0, 0),
 65            text=header_text,
 66            h_align='center',
 67            v_align='center',
 68            maxwidth=self._width * 0.9 - 120,
 69            scale=1.2,
 70            color=(1, 0.8, 0.3, 1),
 71        )
 72        size = store.get_store_item_display_size(items[0])
 73        display: dict[str, Any] = {}
 74        instantiate_store_item_display(
 75            items[0],
 76            display,
 77            parent_widget=self._root_widget,
 78            b_pos=(
 79                self._width * 0.5
 80                - size[0] * 0.5
 81                + 10
 82                - ((size[0] * 0.5 + 30) if self._is_double else 0),
 83                self._height * 0.5
 84                - size[1] * 0.5
 85                + 30
 86                + (20 if self._is_double else 0),
 87            ),
 88            b_width=size[0],
 89            b_height=size[1],
 90            button=False,
 91        )
 92
 93        # Wire up the parts we need.
 94        if self._is_double:
 95            pass  # not working
 96        else:
 97            if self._items == ['pro']:
 98                price_str = plus.get_price(self._items[0])
 99                pyoffs = -15
100            else:
101                pyoffs = 0
102                price = self._price = plus.get_v1_account_misc_read_val(
103                    'price.' + str(items[0]), -1
104                )
105                price_str = bui.charstr(bui.SpecialChar.TICKET) + str(price)
106            self._price_text = bui.textwidget(
107                parent=self._root_widget,
108                position=(self._width * 0.5, 150 + pyoffs),
109                size=(0, 0),
110                text=price_str,
111                h_align='center',
112                v_align='center',
113                maxwidth=self._width * 0.9,
114                scale=1.4,
115                color=(0.2, 1, 0.2),
116            )
117
118        self._update_timer = bui.AppTimer(
119            1.0, bui.WeakCall(self._update), repeat=True
120        )
121
122        self._cancel_button = bui.buttonwidget(
123            parent=self._root_widget,
124            position=(50, 40),
125            size=(150, 60),
126            scale=1.0,
127            on_activate_call=self._cancel,
128            autoselect=True,
129            label=bui.Lstr(resource='cancelText'),
130        )
131        self._purchase_button = bui.buttonwidget(
132            parent=self._root_widget,
133            position=(self._width - 200, 40),
134            size=(150, 60),
135            scale=1.0,
136            on_activate_call=self._purchase,
137            autoselect=True,
138            label=bui.Lstr(resource='store.purchaseText'),
139        )
140
141        bui.containerwidget(
142            edit=self._root_widget,
143            cancel_button=self._cancel_button,
144            start_button=self._purchase_button,
145            selected_child=self._purchase_button,
146        )
147
148    def _update(self) -> None:
149        can_die = False
150
151        plus = bui.app.plus
152        assert plus is not None
153
154        # We go away if we see that our target item is owned.
155        if self._items == ['pro']:
156            assert bui.app.classic is not None
157            if bui.app.classic.accounts.have_pro():
158                can_die = True
159        else:
160            if plus.get_purchased(self._items[0]):
161                can_die = True
162
163        if can_die:
164            bui.containerwidget(edit=self._root_widget, transition='out_left')
165
166    def _purchase(self) -> None:
167        from bauiv1lib import getcurrency
168
169        plus = bui.app.plus
170        assert plus is not None
171
172        if self._items == ['pro']:
173            plus.purchase('pro')
174        else:
175            ticket_count: int | None
176            try:
177                ticket_count = plus.get_v1_account_ticket_count()
178            except Exception:
179                ticket_count = None
180            if ticket_count is not None and ticket_count < self._price:
181                getcurrency.show_get_tickets_prompt()
182                bui.getsound('error').play()
183                return
184
185            def do_it() -> None:
186                assert plus is not None
187
188                plus.in_game_purchase(self._items[0], self._price)
189
190            bui.getsound('swish').play()
191            do_it()
192
193    def _cancel(self) -> None:
194        bui.containerwidget(edit=self._root_widget, transition='out_right')
class PurchaseWindow(bauiv1._uitypes.Window):
 16class PurchaseWindow(bui.Window):
 17    """Window for purchasing one or more items."""
 18
 19    def __init__(
 20        self,
 21        items: list[str],
 22        transition: str = 'in_right',
 23        header_text: bui.Lstr | None = None,
 24    ):
 25        from bauiv1lib.store.item import instantiate_store_item_display
 26
 27        plus = bui.app.plus
 28        assert plus is not None
 29
 30        assert bui.app.classic is not None
 31        store = bui.app.classic.store
 32
 33        if header_text is None:
 34            header_text = bui.Lstr(
 35                resource='unlockThisText',
 36                fallback_resource='unlockThisInTheStoreText',
 37            )
 38        if len(items) != 1:
 39            raise ValueError('expected exactly 1 item')
 40        self._items = list(items)
 41        self._width = 580
 42        self._height = 520
 43        uiscale = bui.app.ui_v1.uiscale
 44        super().__init__(
 45            root_widget=bui.containerwidget(
 46                size=(self._width, self._height),
 47                transition=transition,
 48                toolbar_visibility='menu_currency',
 49                scale=(
 50                    1.2
 51                    if uiscale is bui.UIScale.SMALL
 52                    else 1.1
 53                    if uiscale is bui.UIScale.MEDIUM
 54                    else 1.0
 55                ),
 56                stack_offset=(0, -15)
 57                if uiscale is bui.UIScale.SMALL
 58                else (0, 0),
 59            )
 60        )
 61        self._is_double = False
 62        self._title_text = bui.textwidget(
 63            parent=self._root_widget,
 64            position=(self._width * 0.5, self._height - 30),
 65            size=(0, 0),
 66            text=header_text,
 67            h_align='center',
 68            v_align='center',
 69            maxwidth=self._width * 0.9 - 120,
 70            scale=1.2,
 71            color=(1, 0.8, 0.3, 1),
 72        )
 73        size = store.get_store_item_display_size(items[0])
 74        display: dict[str, Any] = {}
 75        instantiate_store_item_display(
 76            items[0],
 77            display,
 78            parent_widget=self._root_widget,
 79            b_pos=(
 80                self._width * 0.5
 81                - size[0] * 0.5
 82                + 10
 83                - ((size[0] * 0.5 + 30) if self._is_double else 0),
 84                self._height * 0.5
 85                - size[1] * 0.5
 86                + 30
 87                + (20 if self._is_double else 0),
 88            ),
 89            b_width=size[0],
 90            b_height=size[1],
 91            button=False,
 92        )
 93
 94        # Wire up the parts we need.
 95        if self._is_double:
 96            pass  # not working
 97        else:
 98            if self._items == ['pro']:
 99                price_str = plus.get_price(self._items[0])
100                pyoffs = -15
101            else:
102                pyoffs = 0
103                price = self._price = plus.get_v1_account_misc_read_val(
104                    'price.' + str(items[0]), -1
105                )
106                price_str = bui.charstr(bui.SpecialChar.TICKET) + str(price)
107            self._price_text = bui.textwidget(
108                parent=self._root_widget,
109                position=(self._width * 0.5, 150 + pyoffs),
110                size=(0, 0),
111                text=price_str,
112                h_align='center',
113                v_align='center',
114                maxwidth=self._width * 0.9,
115                scale=1.4,
116                color=(0.2, 1, 0.2),
117            )
118
119        self._update_timer = bui.AppTimer(
120            1.0, bui.WeakCall(self._update), repeat=True
121        )
122
123        self._cancel_button = bui.buttonwidget(
124            parent=self._root_widget,
125            position=(50, 40),
126            size=(150, 60),
127            scale=1.0,
128            on_activate_call=self._cancel,
129            autoselect=True,
130            label=bui.Lstr(resource='cancelText'),
131        )
132        self._purchase_button = bui.buttonwidget(
133            parent=self._root_widget,
134            position=(self._width - 200, 40),
135            size=(150, 60),
136            scale=1.0,
137            on_activate_call=self._purchase,
138            autoselect=True,
139            label=bui.Lstr(resource='store.purchaseText'),
140        )
141
142        bui.containerwidget(
143            edit=self._root_widget,
144            cancel_button=self._cancel_button,
145            start_button=self._purchase_button,
146            selected_child=self._purchase_button,
147        )
148
149    def _update(self) -> None:
150        can_die = False
151
152        plus = bui.app.plus
153        assert plus is not None
154
155        # We go away if we see that our target item is owned.
156        if self._items == ['pro']:
157            assert bui.app.classic is not None
158            if bui.app.classic.accounts.have_pro():
159                can_die = True
160        else:
161            if plus.get_purchased(self._items[0]):
162                can_die = True
163
164        if can_die:
165            bui.containerwidget(edit=self._root_widget, transition='out_left')
166
167    def _purchase(self) -> None:
168        from bauiv1lib import getcurrency
169
170        plus = bui.app.plus
171        assert plus is not None
172
173        if self._items == ['pro']:
174            plus.purchase('pro')
175        else:
176            ticket_count: int | None
177            try:
178                ticket_count = plus.get_v1_account_ticket_count()
179            except Exception:
180                ticket_count = None
181            if ticket_count is not None and ticket_count < self._price:
182                getcurrency.show_get_tickets_prompt()
183                bui.getsound('error').play()
184                return
185
186            def do_it() -> None:
187                assert plus is not None
188
189                plus.in_game_purchase(self._items[0], self._price)
190
191            bui.getsound('swish').play()
192            do_it()
193
194    def _cancel(self) -> None:
195        bui.containerwidget(edit=self._root_widget, transition='out_right')

Window for purchasing one or more items.

PurchaseWindow( items: list[str], transition: str = 'in_right', header_text: babase._language.Lstr | None = None)
 19    def __init__(
 20        self,
 21        items: list[str],
 22        transition: str = 'in_right',
 23        header_text: bui.Lstr | None = None,
 24    ):
 25        from bauiv1lib.store.item import instantiate_store_item_display
 26
 27        plus = bui.app.plus
 28        assert plus is not None
 29
 30        assert bui.app.classic is not None
 31        store = bui.app.classic.store
 32
 33        if header_text is None:
 34            header_text = bui.Lstr(
 35                resource='unlockThisText',
 36                fallback_resource='unlockThisInTheStoreText',
 37            )
 38        if len(items) != 1:
 39            raise ValueError('expected exactly 1 item')
 40        self._items = list(items)
 41        self._width = 580
 42        self._height = 520
 43        uiscale = bui.app.ui_v1.uiscale
 44        super().__init__(
 45            root_widget=bui.containerwidget(
 46                size=(self._width, self._height),
 47                transition=transition,
 48                toolbar_visibility='menu_currency',
 49                scale=(
 50                    1.2
 51                    if uiscale is bui.UIScale.SMALL
 52                    else 1.1
 53                    if uiscale is bui.UIScale.MEDIUM
 54                    else 1.0
 55                ),
 56                stack_offset=(0, -15)
 57                if uiscale is bui.UIScale.SMALL
 58                else (0, 0),
 59            )
 60        )
 61        self._is_double = False
 62        self._title_text = bui.textwidget(
 63            parent=self._root_widget,
 64            position=(self._width * 0.5, self._height - 30),
 65            size=(0, 0),
 66            text=header_text,
 67            h_align='center',
 68            v_align='center',
 69            maxwidth=self._width * 0.9 - 120,
 70            scale=1.2,
 71            color=(1, 0.8, 0.3, 1),
 72        )
 73        size = store.get_store_item_display_size(items[0])
 74        display: dict[str, Any] = {}
 75        instantiate_store_item_display(
 76            items[0],
 77            display,
 78            parent_widget=self._root_widget,
 79            b_pos=(
 80                self._width * 0.5
 81                - size[0] * 0.5
 82                + 10
 83                - ((size[0] * 0.5 + 30) if self._is_double else 0),
 84                self._height * 0.5
 85                - size[1] * 0.5
 86                + 30
 87                + (20 if self._is_double else 0),
 88            ),
 89            b_width=size[0],
 90            b_height=size[1],
 91            button=False,
 92        )
 93
 94        # Wire up the parts we need.
 95        if self._is_double:
 96            pass  # not working
 97        else:
 98            if self._items == ['pro']:
 99                price_str = plus.get_price(self._items[0])
100                pyoffs = -15
101            else:
102                pyoffs = 0
103                price = self._price = plus.get_v1_account_misc_read_val(
104                    'price.' + str(items[0]), -1
105                )
106                price_str = bui.charstr(bui.SpecialChar.TICKET) + str(price)
107            self._price_text = bui.textwidget(
108                parent=self._root_widget,
109                position=(self._width * 0.5, 150 + pyoffs),
110                size=(0, 0),
111                text=price_str,
112                h_align='center',
113                v_align='center',
114                maxwidth=self._width * 0.9,
115                scale=1.4,
116                color=(0.2, 1, 0.2),
117            )
118
119        self._update_timer = bui.AppTimer(
120            1.0, bui.WeakCall(self._update), repeat=True
121        )
122
123        self._cancel_button = bui.buttonwidget(
124            parent=self._root_widget,
125            position=(50, 40),
126            size=(150, 60),
127            scale=1.0,
128            on_activate_call=self._cancel,
129            autoselect=True,
130            label=bui.Lstr(resource='cancelText'),
131        )
132        self._purchase_button = bui.buttonwidget(
133            parent=self._root_widget,
134            position=(self._width - 200, 40),
135            size=(150, 60),
136            scale=1.0,
137            on_activate_call=self._purchase,
138            autoselect=True,
139            label=bui.Lstr(resource='store.purchaseText'),
140        )
141
142        bui.containerwidget(
143            edit=self._root_widget,
144            cancel_button=self._cancel_button,
145            start_button=self._purchase_button,
146            selected_child=self._purchase_button,
147        )
Inherited Members
bauiv1._uitypes.Window
get_root_widget